[mame] 01/04: New upstream version 0.181

Jordi Mallach jordi at moszumanska.debian.org
Wed Dec 28 11:02:01 UTC 2016


This is an automated email from the git hooks/post-receive script.

jordi pushed a commit to branch master
in repository mame.

commit b100aa9b2d36e9f5368eee228fec2f492cb1a4a3
Author: Jordi Mallach <jordi at debian.org>
Date:   Wed Dec 28 11:42:37 2016 +0100

    New upstream version 0.181
---
 3rdparty/lua-zlib/lua_zlib.c                       |    2 +-
 android-project/app/src/main/AndroidManifest.xml   |    4 +-
 hash/a7800.xml                                     |    2 +-
 hash/apple1.xml                                    |    6 +-
 hash/apple2.xml                                    |    2 +-
 hash/apricot_flop.xml                              |   98 +
 hash/hp_ipc.xml                                    |  461 +++++
 hash/ibm5150.xml                                   | 1381 +++++++++++---
 hash/ibm5160_flop.xml                              |   17 -
 hash/ibm5170.xml                                   |  770 +++-----
 hash/neogeo.xml                                    |   77 +-
 hash/pcw.xml                                       |   22 +-
 hlsl/phosphor.fx                                   |   12 +-
 language/Catalan/strings.po                        |   51 +-
 makefile                                           |   12 +-
 nl_examples/diode.c                                |   31 +
 nl_examples/norton_opamp.c                         |  127 ++
 nl_examples/rc.c                                   |   31 +
 nl_examples/rl.c                                   |   32 +
 plugins/hiscore/hiscore.dat                        |   54 +-
 projects/README.md                                 |    4 +
 scripts/build/png2bdc.py                           |  109 +-
 scripts/font/NotoSans-Bold.bdc                     |  Bin 52993 -> 61317 bytes
 scripts/genie.lua                                  |   22 +-
 scripts/resources/uwp/mame_TemporaryKey.pfx        |  Bin 0 -> 2454 bytes
 scripts/src/bus.lua                                |    1 +
 scripts/src/cpu.lua                                |    5 +-
 scripts/src/emu.lua                                |    3 -
 scripts/src/machine.lua                            |   25 +
 scripts/src/main.lua                               |    4 +
 scripts/src/netlist.lua                            |   38 +
 scripts/src/sound.lua                              |   23 +
 scripts/src/video.lua                              |   12 +
 scripts/target/mame/arcade.lua                     |   31 +-
 scripts/target/mame/mess.lua                       |   20 +-
 scripts/target/mame/nl.lua                         |   12 +
 scripts/target/mame/tiny.lua                       |    2 -
 src/devices/bus/a2bus/a2midi.cpp                   |    3 +-
 src/devices/bus/a7800/a78_carts.h                  |    1 +
 src/devices/bus/a7800/a78_slot.cpp                 |   15 +-
 src/devices/bus/a7800/a78_slot.h                   |    3 +-
 src/devices/bus/a7800/rom.cpp                      |   40 +
 src/devices/bus/a7800/rom.h                        |   16 +
 src/devices/bus/amiga/zorro/buddha.cpp             |  145 +-
 src/devices/bus/amiga/zorro/buddha.h               |    2 +
 src/devices/bus/apricot/keyboard/hle.cpp           |   10 +
 src/devices/bus/apricot/keyboard/hle.h             |    7 +-
 src/devices/bus/c64/magic_voice.cpp                |    8 +-
 src/devices/bus/c64/midi_passport.cpp              |    3 +-
 src/devices/bus/coco/coco_t4426.cpp                |  201 +++
 src/devices/bus/coco/coco_t4426.h                  |   56 +
 src/devices/bus/isbx/isbc_218a.cpp                 |   11 +-
 src/devices/bus/isbx/isbc_218a.h                   |    2 +-
 src/devices/bus/ti99x/gromport.cpp                 |   20 +-
 src/devices/bus/ti99x/gromport.h                   |    6 +-
 src/devices/cpu/arm/arm.cpp                        |   22 +-
 src/devices/cpu/cop400/cop400.cpp                  |   13 +-
 src/devices/cpu/cop400/cop400.h                    |    5 +
 src/devices/cpu/cop400/cop400op.hxx                |    5 +
 src/devices/cpu/drcbex64.cpp                       |    6 +
 src/devices/cpu/i8089/i8089_channel.cpp            |    7 +-
 src/devices/cpu/i86/i186.cpp                       |   17 +-
 src/devices/cpu/i86/i286.cpp                       |  118 +-
 src/devices/cpu/i86/i286.h                         |   10 +-
 src/devices/cpu/i86/i86.cpp                        |   75 +-
 src/devices/cpu/i86/i86.h                          |    7 +-
 src/devices/cpu/i960/i960.cpp                      |   83 +
 src/devices/cpu/i960/i960.h                        |    1 +
 src/devices/cpu/i960/i960dis.cpp                   |    2 +-
 src/devices/cpu/m68000/m68kcpu.h                   |    8 +-
 src/devices/cpu/m68000/makefile                    |    4 +-
 src/devices/cpu/m6805/m6805.cpp                    |  163 ++
 src/devices/cpu/m6805/m6805.h                      |  106 ++
 src/devices/cpu/mb86235/mb86235.cpp                |  248 ++-
 src/devices/cpu/mb86235/mb86235.h                  |  213 ++-
 src/devices/cpu/mb86235/mb86235drc.cpp             | 1889 ++++++++++++++++++++
 src/devices/cpu/mb86235/mb86235fe.cpp              |  922 ++++++++++
 src/devices/cpu/mb86235/mb86235fe.h                |   47 +
 src/devices/cpu/powerpc/ppc.h                      |    1 +
 src/devices/cpu/powerpc/ppccom.cpp                 |   21 +
 src/devices/cpu/powerpc/ppccom.h                   |   18 +-
 src/devices/cpu/powerpc/ppcdrc.cpp                 |   26 +-
 src/devices/cpu/sharc/sharc.cpp                    |  243 +--
 src/devices/cpu/sharc/sharc.h                      |   24 +-
 src/devices/cpu/sharc/sharcdrc.cpp                 |  338 +---
 src/devices/cpu/sharc/sharcmem.hxx                 |  179 +-
 src/devices/cpu/tms32025/tms32025.cpp              |  730 +++-----
 src/devices/cpu/tms32025/tms32025.h                |   59 +-
 src/devices/cpu/tms32051/tms32051.cpp              |   20 -
 src/devices/cpu/tms32051/tms32051.h                |    1 -
 src/devices/cpu/v810/v810.cpp                      |    2 +-
 src/devices/cpu/v810/v810.h                        |    2 +-
 src/devices/cpu/v810/v810dasm.cpp                  |    2 +-
 src/devices/cpu/z80/z80.cpp                        |    6 +
 src/devices/imagedev/floppy.cpp                    |    4 +
 src/devices/machine/40105.cpp                      |  143 +-
 src/devices/machine/40105.h                        |   55 +-
 src/devices/machine/68230pit.cpp                   |  295 ++-
 src/devices/machine/68230pit.h                     |  148 +-
 src/devices/machine/6840ptm.cpp                    |   41 +-
 src/devices/machine/6840ptm.h                      |    5 -
 src/devices/machine/74157.cpp                      |  219 +++
 src/devices/machine/74157.h                        |  104 ++
 src/devices/machine/82s129.cpp                     |    2 +-
 src/devices/machine/atahle.cpp                     |    2 +-
 src/devices/machine/cdp1879.cpp                    |  152 ++
 src/devices/machine/cdp1879.h                      |   85 +
 src/devices/machine/genpc.cpp                      |    4 +-
 src/devices/machine/i8155.cpp                      |   47 +-
 src/devices/machine/idehd.cpp                      |    2 +-
 src/devices/machine/laserdsc.cpp                   |   18 +-
 src/devices/machine/laserdsc.h                     |    4 +-
 src/devices/machine/microtch.cpp                   |   32 +-
 src/devices/machine/netlist.cpp                    |   77 +-
 src/devices/machine/netlist.h                      |   84 +-
 src/devices/machine/pci-ide.cpp                    |    4 +-
 src/devices/machine/pci.cpp                        |    5 +-
 src/devices/machine/pci.h                          |    4 +-
 src/devices/machine/pci9050.cpp                    |   16 +-
 src/devices/machine/pci9050.h                      |   12 +-
 src/devices/machine/pit8253.cpp                    |   12 +-
 src/devices/machine/scnxx562.cpp                   |    4 +-
 src/devices/machine/upd765.cpp                     |    2 +-
 src/devices/machine/wd_fdc.cpp                     |   12 +-
 src/devices/machine/wd_fdc.h                       |    6 +-
 src/devices/machine/z80dart.cpp                    |   20 +-
 src/devices/machine/z80scc.cpp                     |  588 +++---
 src/devices/machine/z80scc.h                       |    4 +-
 src/devices/sound/dac76.cpp                        |   91 +
 src/devices/sound/dac76.h                          |   76 +
 src/devices/sound/k054539.cpp                      |   10 +
 src/devices/sound/k056800.cpp                      |    1 +
 src/devices/sound/mm5837.cpp                       |   90 +
 src/devices/sound/mm5837.h                         |   81 +
 src/devices/sound/msm5205.cpp                      |    5 +
 src/devices/sound/msm5205.h                        |    4 +
 src/devices/sound/votrax.cpp                       | 1820 ++++++++-----------
 src/devices/sound/votrax.h                         |  267 +--
 src/devices/video/ef9369.cpp                       |  104 ++
 src/devices/video/ef9369.h                         |   87 +
 src/devices/video/poly.h                           |    1 +
 src/devices/video/zeus2.cpp                        |  699 +++++---
 src/devices/video/zeus2.h                          |   27 +-
 src/emu/addrmap.cpp                                |    8 +-
 src/emu/bookkeeping.cpp                            |   20 +-
 src/emu/bookkeeping.h                              |    4 +-
 src/emu/config.cpp                                 |  108 +-
 src/emu/config.h                                   |   29 +-
 src/emu/crsshair.cpp                               |   36 +-
 src/emu/crsshair.h                                 |    4 +-
 src/emu/debug/debugcmd.cpp                         |   10 +
 src/emu/debug/debugcpu.cpp                         |   73 +-
 src/emu/debug/debugcpu.h                           |   10 +-
 src/emu/devcb.cpp                                  |  188 +-
 src/emu/devcb.h                                    |  149 +-
 src/emu/dimemory.cpp                               |   46 -
 src/emu/dimemory.h                                 |    8 -
 src/emu/dispatch.cpp                               |   40 -
 src/emu/dispatch.h                                 |   64 -
 src/emu/drivers/xtal.h                             |    1 +
 src/emu/emu.h                                      |    1 -
 src/emu/image.cpp                                  |   30 +-
 src/emu/image.h                                    |   12 +-
 src/emu/ioport.cpp                                 |   54 +-
 src/emu/ioport.h                                   |   18 +-
 src/emu/main.h                                     |    2 +-
 src/emu/network.cpp                                |   17 +-
 src/emu/network.h                                  |   10 +-
 src/emu/render.cpp                                 |   32 +-
 src/emu/render.h                                   |   52 +-
 src/emu/rendfont.cpp                               | 1381 +++++++++++---
 src/emu/rendfont.h                                 |   41 +-
 src/emu/rendlay.cpp                                |   74 +-
 src/emu/sound.cpp                                  |   14 +-
 src/emu/sound.h                                    |    4 +-
 src/emu/ui/cmddata.h                               |  220 +--
 src/emu/ui/cmdrender.h                             |  150 --
 src/emu/uiinput.cpp                                |    9 +-
 src/frontend/mame/cheat.cpp                        |   42 +-
 src/frontend/mame/cheat.h                          |   18 +-
 src/frontend/mame/clifront.cpp                     |   16 +-
 src/frontend/mame/info.cpp                         |   82 +-
 src/frontend/mame/luaengine.cpp                    |    2 +-
 src/frontend/mame/mame.cpp                         |   11 +-
 src/frontend/mame/media_ident.cpp                  |    4 +-
 src/frontend/mame/ui/filesel.cpp                   |   17 +-
 src/frontend/mame/ui/filesel.h                     |    3 +
 src/frontend/mame/ui/selmenu.cpp                   |   87 +-
 src/frontend/mame/ui/selmenu.h                     |   35 +-
 src/lib/formats/acorn_dsk.cpp                      |    4 +-
 src/lib/netlist/analog/nld_opamps.cpp              |   16 +
 src/lib/netlist/analog/nld_twoterm.cpp             |   21 +
 src/lib/netlist/analog/nld_twoterm.h               |   61 +-
 src/lib/netlist/build/makefile                     |   33 +-
 src/lib/netlist/devices/net_lib.cpp                |   47 +-
 src/lib/netlist/devices/net_lib.h                  |   20 +
 src/lib/netlist/devices/nld_2102A.cpp              |  103 ++
 src/lib/netlist/devices/nld_2102A.h                |   48 +
 src/lib/netlist/devices/nld_2716.cpp               |  101 ++
 src/lib/netlist/devices/nld_2716.h                 |   52 +
 src/lib/netlist/devices/nld_4066.h                 |    2 +-
 src/lib/netlist/devices/nld_4316.cpp               |   49 +
 src/lib/netlist/devices/nld_4316.h                 |   33 +
 src/lib/netlist/devices/nld_74107.cpp              |   19 +-
 src/lib/netlist/devices/nld_74107.h                |   13 +-
 src/lib/netlist/devices/nld_74161.cpp              |  133 ++
 src/lib/netlist/devices/nld_74161.h                |   45 +
 src/lib/netlist/devices/nld_74165.cpp              |  107 ++
 src/lib/netlist/devices/nld_74165.h                |   50 +
 src/lib/netlist/devices/nld_74166.cpp              |  127 ++
 src/lib/netlist/devices/nld_74166.h                |   51 +
 src/lib/netlist/devices/nld_74174.cpp              |  140 ++
 src/lib/netlist/devices/nld_74174.h                |   56 +
 src/lib/netlist/devices/nld_74175.h                |   11 +-
 src/lib/netlist/devices/nld_74192.h                |   12 +-
 src/lib/netlist/devices/nld_74193.h                |   12 +-
 src/lib/netlist/devices/nld_74194.cpp              |  122 ++
 src/lib/netlist/devices/nld_74194.h                |   47 +
 src/lib/netlist/devices/nld_74365.cpp              |   74 +
 src/lib/netlist/devices/nld_74365.h                |   44 +
 src/lib/netlist/devices/nld_7473.cpp               |  150 ++
 .../netlist/devices/{nld_74107.h => nld_7473.h}    |   61 +-
 src/lib/netlist/devices/nld_7475.cpp               |  156 ++
 src/lib/netlist/devices/nld_7475.h                 |   62 +
 src/lib/netlist/devices/nld_7485.cpp               |  107 ++
 src/lib/netlist/devices/nld_7485.h                 |   45 +
 src/lib/netlist/devices/nld_82S115.cpp             |  113 ++
 src/lib/netlist/devices/nld_82S115.h               |   51 +
 src/lib/netlist/devices/nld_82S123.cpp             |   84 +
 src/lib/netlist/devices/nld_82S123.h               |   42 +
 src/lib/netlist/devices/nld_82S126.cpp             |   86 +
 src/lib/netlist/devices/nld_82S126.h               |   45 +
 src/lib/netlist/devices/nld_9312.h                 |   16 +-
 src/lib/netlist/devices/nld_9316.h                 |    2 +
 src/lib/netlist/devices/nld_9322.cpp               |  114 ++
 src/lib/netlist/devices/nld_9322.h                 |   42 +
 src/lib/netlist/devices/nld_am2847.cpp             |  129 ++
 src/lib/netlist/devices/nld_am2847.h               |   41 +
 src/lib/netlist/devices/nld_dm9334.cpp             |  149 ++
 src/lib/netlist/devices/nld_dm9334.h               |   82 +
 src/lib/netlist/devices/nld_tristate.cpp           |   76 +
 src/lib/netlist/devices/nld_tristate.h             |   31 +
 src/lib/netlist/macro/nlm_cd4xxx.cpp               |   79 +-
 src/lib/netlist/macro/nlm_cd4xxx.h                 |    3 +
 src/lib/netlist/macro/nlm_opamp.cpp                |  120 +-
 src/lib/netlist/macro/nlm_ttl74xx.cpp              |   61 +
 src/lib/netlist/macro/nlm_ttl74xx.h                |   15 +
 src/lib/netlist/nl_base.cpp                        |    1 +
 src/lib/netlist/nl_base.h                          |    5 +-
 src/lib/netlist/nl_setup.cpp                       |    3 +
 src/lib/netlist/prg/nltool.cpp                     |    3 +
 src/lib/util/bitmap.cpp                            |  103 +-
 src/lib/util/bitmap.h                              |   86 +-
 src/lib/util/coretmpl.h                            |  389 +++-
 src/lib/util/delegate.h                            |    2 +-
 src/lib/util/xmlfile.cpp                           |  199 ++-
 src/lib/util/xmlfile.h                             |   95 +-
 src/mame/arcade.flt                                |    2 +
 src/mame/audio/8080bw.cpp                          |    1 +
 src/mame/audio/beezer.cpp                          |  482 -----
 src/mame/audio/csd.cpp                             |  180 ++
 src/mame/audio/csd.h                               |   64 +
 src/mame/audio/dcs.cpp                             |   73 +-
 src/mame/audio/dcs.h                               |    3 +
 src/mame/audio/gorf.cpp                            |  190 --
 src/mame/audio/gorf.h                              |    4 -
 src/mame/audio/gottlieb.cpp                        |  240 ---
 src/mame/audio/gottlieb.h                          |   25 -
 src/mame/audio/midway.cpp                          |  203 +--
 src/mame/audio/midway.h                            |   41 -
 src/mame/audio/wow.cpp                             |  183 --
 src/mame/audio/wow.h                               |    4 -
 src/mame/drivers/24cdjuke.cpp                      |    2 +-
 src/mame/drivers/4enraya.cpp                       |    2 +-
 src/mame/drivers/8080bw.cpp                        |    8 +-
 src/mame/drivers/aa310.cpp                         |    8 +-
 src/mame/drivers/adp.cpp                           |    2 +-
 src/mame/drivers/aerofgt.cpp                       |   78 +-
 src/mame/drivers/airraid.cpp                       |    2 +-
 src/mame/drivers/amstrad.cpp                       |    2 +-
 src/mame/drivers/amusco.cpp                        |   36 +-
 src/mame/drivers/apricot.cpp                       |   19 +-
 src/mame/drivers/arachnid.cpp                      |    3 +-
 src/mame/drivers/aristmk5.cpp                      |  483 +++--
 src/mame/drivers/aristmk6.cpp                      |    2 +-
 src/mame/drivers/armedf.cpp                        |    1 +
 src/mame/drivers/astinvad.cpp                      |   85 +-
 src/mame/drivers/astrocde.cpp                      |   55 +-
 src/mame/drivers/atarittl.cpp                      |   16 +-
 src/mame/drivers/atlantis.cpp                      |   87 +-
 src/mame/drivers/attckufo.cpp                      |    2 +-
 src/mame/drivers/aussiebyte.cpp                    |   29 +-
 src/mame/drivers/beezer.cpp                        |  609 ++++++-
 src/mame/drivers/bfm_sc2.cpp                       |   19 +
 src/mame/drivers/bmcbowl.cpp                       |    2 +-
 src/mame/drivers/bublbobl.cpp                      |   55 +-
 src/mame/drivers/by35.cpp                          |    2 +-
 src/mame/drivers/cardline.cpp                      |    2 +-
 src/mame/drivers/ccastles.cpp                      |   14 +-
 src/mame/drivers/cchance.cpp                       |   21 +-
 src/mame/drivers/cchasm.cpp                        |    3 +-
 src/mame/drivers/cedar_magnet.cpp                  |   14 +-
 src/mame/drivers/chanbara.cpp                      |    2 +-
 src/mame/drivers/chihiro.cpp                       |   49 +-
 src/mame/drivers/clcd.cpp                          |   21 +-
 src/mame/drivers/cmi.cpp                           |   15 +-
 src/mame/drivers/coco12.cpp                        |   26 +-
 src/mame/drivers/cps1.cpp                          |    2 +-
 src/mame/drivers/ct486.cpp                         |    1 -
 src/mame/drivers/d9final.cpp                       |    1 +
 src/mame/drivers/darkmist.cpp                      |    4 +
 src/mame/drivers/ddealer.cpp                       |  104 +-
 src/mame/drivers/de_2.cpp                          |   34 +-
 src/mame/drivers/dec0.cpp                          |  210 ++-
 src/mame/drivers/dec8.cpp                          |    6 +-
 src/mame/drivers/discoboy.cpp                      |   33 +-
 src/mame/drivers/dmv.cpp                           |    8 +-
 src/mame/drivers/dominob.cpp                       |    2 +-
 src/mame/drivers/dorachan.cpp                      |    2 +-
 src/mame/drivers/dynadice.cpp                      |    2 +-
 src/mame/drivers/dynduke.cpp                       |   30 +-
 src/mame/drivers/eolith.cpp                        |    2 +-
 src/mame/drivers/epos.cpp                          |   52 +-
 src/mame/drivers/equites.cpp                       |   84 +-
 src/mame/drivers/ertictac.cpp                      |    7 +-
 src/mame/drivers/esq5505.cpp                       |   17 +
 src/mame/drivers/esripsys.cpp                      |    3 +-
 src/mame/drivers/expro02.cpp                       |   38 +-
 src/mame/drivers/fccpu20.cpp                       |  287 +++
 src/mame/drivers/fccpu30.cpp                       |    4 +-
 src/mame/drivers/fcombat.cpp                       |    2 +-
 src/mame/drivers/fcrash.cpp                        |   12 +-
 src/mame/drivers/fidel6502.cpp                     |   25 +-
 src/mame/drivers/freekick.cpp                      |    2 +-
 src/mame/drivers/fromance.cpp                      |   21 +-
 src/mame/drivers/gaiden.cpp                        |    2 +-
 src/mame/drivers/galaxian.cpp                      |   20 +
 src/mame/drivers/gammagic.cpp                      |    1 -
 src/mame/drivers/gcpinbal.cpp                      |   41 +-
 src/mame/drivers/genpc.cpp                         |  122 +-
 src/mame/drivers/ginganin.cpp                      |    3 +-
 src/mame/drivers/gkigt.cpp                         |   96 +-
 src/mame/drivers/gottlieb.cpp                      |   35 -
 src/mame/drivers/guab.cpp                          |  655 ++++---
 src/mame/drivers/hanaawas.cpp                      |   52 +-
 src/mame/drivers/hazeltin.cpp                      |  598 +++----
 src/mame/drivers/hh_amis2k.cpp                     |    2 +-
 src/mame/drivers/hh_cop400.cpp                     |  182 +-
 src/mame/drivers/hikaru.cpp                        |    4 +-
 src/mame/drivers/homedata.cpp                      |   60 +-
 src/mame/drivers/homerun.cpp                       |    2 +-
 src/mame/drivers/hp9k_3xx.cpp                      |   21 +-
 src/mame/drivers/ibmpc.cpp                         |    1 -
 src/mame/drivers/imolagp.cpp                       |    4 +-
 src/mame/drivers/inder.cpp                         |   44 +-
 src/mame/drivers/isbc.cpp                          |   68 +-
 src/mame/drivers/iteagle.cpp                       |    6 +-
 src/mame/drivers/itech32.cpp                       |    4 +-
 src/mame/drivers/jpmsys5.cpp                       |    9 +-
 src/mame/drivers/k28.cpp                           |    7 +-
 src/mame/drivers/kaneko16.cpp                      |  125 +-
 src/mame/drivers/koftball.cpp                      |    2 +-
 src/mame/drivers/koikoi.cpp                        |    2 +-
 src/mame/drivers/konamigx.cpp                      |   10 +
 src/mame/drivers/kopunch.cpp                       |    6 +-
 src/mame/drivers/ksayakyu.cpp                      |    2 +-
 src/mame/drivers/ksys573.cpp                       |   45 +-
 src/mame/drivers/ladybug.cpp                       |   18 +-
 src/mame/drivers/ladyfrog.cpp                      |    2 +-
 src/mame/drivers/laserbas.cpp                      |    2 +-
 src/mame/drivers/leland.cpp                        |    8 +-
 src/mame/drivers/lwriter.cpp                       |  231 +++
 src/mame/drivers/mac128.cpp                        |   69 +-
 src/mame/drivers/magnum.cpp                        |  182 ++
 src/mame/drivers/mc1000.cpp                        |   75 +-
 src/mame/drivers/mcr.cpp                           |    2 +-
 src/mame/drivers/mcr3.cpp                          |   20 +-
 src/mame/drivers/mcr68.cpp                         |  269 +--
 src/mame/drivers/meijinsn.cpp                      |    2 +-
 src/mame/drivers/metro.cpp                         |  158 +-
 src/mame/drivers/meyc8080.cpp                      |    2 +-
 src/mame/drivers/micro20.cpp                       |   85 +-
 src/mame/drivers/midwunit.cpp                      |   70 +-
 src/mame/drivers/mitchell.cpp                      |   86 +-
 src/mame/drivers/mmodular.cpp                      |   20 +-
 src/mame/drivers/model1.cpp                        |   86 +-
 src/mame/drivers/model2.cpp                        |  207 ++-
 src/mame/drivers/model3.cpp                        |   98 +-
 src/mame/drivers/momoko.cpp                        |   86 +-
 src/mame/drivers/mpu3.cpp                          |    3 +-
 src/mame/drivers/mpu4.cpp                          |    6 +-
 src/mame/drivers/mpu4vid.cpp                       |  116 +-
 src/mame/drivers/mustache.cpp                      |   22 +-
 src/mame/drivers/namcos12.cpp                      |    7 +-
 src/mame/drivers/namcos23.cpp                      |   21 +-
 src/mame/drivers/naomi.cpp                         |   10 +-
 src/mame/drivers/nbmj8688.cpp                      |   15 +-
 src/mame/drivers/neodriv.hxx                       |   60 +-
 src/mame/drivers/neptunp2.cpp                      |    2 +-
 src/mame/drivers/nmk16.cpp                         |   52 +-
 src/mame/drivers/nycaptor.cpp                      |    2 +-
 src/mame/drivers/ob68k1a.cpp                       |    3 +-
 src/mame/drivers/othello.cpp                       |    2 +-
 src/mame/drivers/pachifev.cpp                      |    2 +-
 src/mame/drivers/pacman.cpp                        |   90 +-
 src/mame/drivers/pc.cpp                            |   68 +
 src/mame/drivers/peplus.cpp                        |  516 +++---
 src/mame/drivers/pg685.cpp                         |   41 +-
 src/mame/drivers/pgm2.cpp                          |    8 +-
 src/mame/drivers/pgm3.cpp                          |  174 ++
 src/mame/drivers/photon.cpp                        |   76 +-
 src/mame/drivers/pipeline.cpp                      |    2 +-
 src/mame/drivers/pitnrun.cpp                       |    2 +-
 src/mame/drivers/pk8000.cpp                        |  105 +-
 src/mame/drivers/playmark.cpp                      |  206 +--
 src/mame/drivers/poly.cpp                          |    3 +-
 src/mame/drivers/powerbal.cpp                      |   24 +-
 src/mame/drivers/prodigy.cpp                       |   25 +
 src/mame/drivers/pturn.cpp                         |    2 +-
 src/mame/drivers/pulsar.cpp                        |   39 +-
 src/mame/drivers/qix.cpp                           |   19 +
 src/mame/drivers/quizo.cpp                         |    2 +-
 src/mame/drivers/raiden.cpp                        |   93 +-
 src/mame/drivers/rainbow.cpp                       |  507 +++---
 src/mame/drivers/rastan.cpp                        |   24 +-
 src/mame/drivers/rbmk.cpp                          |    2 +-
 src/mame/drivers/rltennis.cpp                      |    2 +-
 src/mame/drivers/s7.cpp                            |    4 +-
 src/mame/drivers/savquest.cpp                      |    7 +-
 src/mame/drivers/segag80r.cpp                      |    4 +-
 src/mame/drivers/segas16b.cpp                      |   68 +-
 src/mame/drivers/segas32.cpp                       |   31 +-
 src/mame/drivers/seta.cpp                          |  120 +-
 src/mame/drivers/sfkick.cpp                        |    2 +-
 src/mame/drivers/sg1000a.cpp                       |    2 +-
 src/mame/drivers/shootout.cpp                      |  132 +-
 src/mame/drivers/sidepckt.cpp                      |   35 +-
 src/mame/drivers/sigmab52.cpp                      |    6 +-
 src/mame/drivers/simple_st0016.cpp                 |    2 +-
 src/mame/drivers/skyarmy.cpp                       |    2 +-
 src/mame/drivers/slapfght.cpp                      |   74 +-
 src/mame/drivers/sliver.cpp                        |    2 +-
 src/mame/drivers/snesb.cpp                         |    2 +-
 src/mame/drivers/sothello.cpp                      |    2 +-
 src/mame/drivers/spbactn.cpp                       |    4 +-
 src/mame/drivers/speglsht.cpp                      |    2 +-
 src/mame/drivers/spinb.cpp                         |   49 +-
 src/mame/drivers/srmp2.cpp                         |   31 +-
 src/mame/drivers/srmp5.cpp                         |    2 +-
 src/mame/drivers/ssfindo.cpp                       |    2 +-
 src/mame/drivers/ssingles.cpp                      |    2 +-
 src/mame/drivers/ssrj.cpp                          |    2 +-
 src/mame/drivers/stv.cpp                           |   65 +-
 src/mame/drivers/superwng.cpp                      |    2 +-
 src/mame/drivers/swtpc09.cpp                       |    9 +-
 src/mame/drivers/system1.cpp                       |   31 +-
 src/mame/drivers/system16.cpp                      |   72 +-
 src/mame/drivers/tail2nos.cpp                      |   81 +-
 src/mame/drivers/taito_o.cpp                       |    2 +-
 src/mame/drivers/taitojc.cpp                       |   71 +-
 src/mame/drivers/taitosj.cpp                       |    2 +-
 src/mame/drivers/tattack.cpp                       |    2 +-
 src/mame/drivers/tavernie.cpp                      |    3 +-
 src/mame/drivers/tcl.cpp                           |    2 +-
 src/mame/drivers/tecmo16.cpp                       |    4 +-
 src/mame/drivers/tmaster.cpp                       |    7 +
 src/mame/drivers/tmnt.cpp                          |   99 +-
 src/mame/drivers/tnzs.cpp                          | 1018 ++++++-----
 src/mame/drivers/toaplan1.cpp                      |  252 ++-
 src/mame/drivers/toaplan2.cpp                      |   79 +-
 src/mame/drivers/tosh1000.cpp                      |  136 ++
 src/mame/drivers/triforce.cpp                      |   36 +-
 src/mame/drivers/v6809.cpp                         |    3 +-
 src/mame/drivers/vaportra.cpp                      |   39 +-
 src/mame/drivers/vega.cpp                          |    2 +-
 src/mame/drivers/vegas.cpp                         |    2 +-
 src/mame/drivers/vis.cpp                           |  199 ++-
 src/mame/drivers/vpoker.cpp                        |    3 +-
 src/mame/drivers/vt100.cpp                         |   14 +-
 src/mame/drivers/whitestar.cpp                     |   36 +-
 src/mame/drivers/witch.cpp                         |    2 +-
 src/mame/drivers/xbox.cpp                          |   10 +-
 src/mame/drivers/yunsung8.cpp                      |  273 +--
 src/mame/drivers/zn.cpp                            |   20 +-
 src/mame/drivers/zwackery.cpp                      |  609 +++++++
 src/mame/drivers/zx.cpp                            |   14 +-
 src/mame/includes/4enraya.h                        |    2 +-
 src/mame/includes/amiga.h                          |    4 +-
 src/mame/includes/archimds.h                       |    3 +-
 src/mame/includes/astrocde.h                       |   11 +-
 src/mame/includes/aussiebyte.h                     |    4 +
 src/mame/includes/beezer.h                         |  123 --
 src/mame/includes/bublbobl.h                       |   37 +-
 src/mame/includes/dec0.h                           |   28 +-
 src/mame/includes/eolith.h                         |    2 +-
 src/mame/includes/epos.h                           |    4 +
 src/mame/includes/equites.h                        |    6 +-
 src/mame/includes/fcombat.h                        |    2 +-
 src/mame/includes/freekick.h                       |    2 +-
 src/mame/includes/fromance.h                       |    3 +-
 src/mame/includes/hanaawas.h                       |    3 +
 src/mame/includes/homerun.h                        |    2 +-
 src/mame/includes/kaneko16.h                       |    5 +
 src/mame/includes/ksayakyu.h                       |    2 +-
 src/mame/includes/ladyfrog.h                       |    2 +-
 src/mame/includes/leland.h                         |   16 +-
 src/mame/includes/mcr.h                            |    5 +-
 src/mame/includes/mcr68.h                          |   69 +-
 src/mame/includes/midwunit.h                       |    6 +-
 src/mame/includes/mitchell.h                       |   17 +-
 src/mame/includes/model1.h                         |    5 +
 src/mame/includes/model2.h                         |    3 +-
 src/mame/includes/mustache.h                       |    7 +-
 src/mame/includes/nycaptor.h                       |    2 +-
 src/mame/includes/pacman.h                         |   21 +-
 src/mame/includes/pitnrun.h                        |    2 +-
 src/mame/includes/pk8000.h                         |   49 +-
 src/mame/includes/playmark.h                       |    5 +-
 src/mame/includes/rastan.h                         |   14 +-
 src/mame/includes/rltennis.h                       |    2 +-
 src/mame/includes/segas16b.h                       |    4 +-
 src/mame/includes/seta.h                           |    2 -
 src/mame/includes/shootout.h                       |    7 +-
 src/mame/includes/sidepckt.h                       |    4 +-
 src/mame/includes/simple_st0016.h                  |    2 +-
 src/mame/includes/slapfght.h                       |   42 +-
 src/mame/includes/srmp2.h                          |    3 +-
 src/mame/includes/ssrj.h                           |    2 +-
 src/mame/includes/system16.h                       |    9 +
 src/mame/includes/tail2nos.h                       |    6 +-
 src/mame/includes/taito_o.h                        |    2 +-
 src/mame/includes/tnzs.h                           |  309 ++--
 src/mame/includes/toaplan1.h                       |   22 +-
 src/mame/includes/toaplan2.h                       |    8 +
 src/mame/includes/vaportra.h                       |    2 +
 src/mame/includes/xbox.h                           |   10 +
 src/mame/includes/{chihiro.h => xbox_nv2a.h}       |   12 +-
 src/mame/includes/yunsung8.h                       |   31 +-
 src/mame/layout/aristmk5.lay                       |  267 +++
 src/mame/layout/funjacks.lay                       |   29 +-
 src/mame/layout/funrlgl.lay                        |   32 +-
 src/mame/layout/guab.lay                           |  166 ++
 src/mame/layout/qkracer.lay                        |   63 +
 src/mame/machine/acitya.cpp                        |  204 ---
 src/mame/machine/acitya.h                          |    2 -
 src/mame/machine/amiga.cpp                         |   24 +-
 src/mame/machine/apollo.cpp                        |    1 -
 src/mame/machine/archimds.cpp                      |   77 +-
 src/mame/machine/at.cpp                            |    1 -
 src/mame/machine/beezer.cpp                        |  144 --
 src/mame/machine/bublbobl.cpp                      |  111 +-
 src/mame/machine/cedar_magnet_sound.cpp            |   65 +-
 src/mame/machine/cedar_magnet_sound.h              |   11 +-
 src/mame/machine/epos.cpp                          |  215 +++
 src/mame/machine/{theglobp.h => epos.h}            |    0
 src/mame/machine/isbc_208.cpp                      |    3 +
 src/mame/machine/iteagle_fpga.cpp                  |  324 +++-
 src/mame/machine/iteagle_fpga.h                    |   39 +-
 src/mame/machine/konamigx.cpp                      |    1 +
 src/mame/machine/leland.cpp                        |   27 +-
 src/mame/machine/m1comm.cpp                        |   12 +-
 src/mame/machine/m1comm.h                          |   12 +-
 src/mame/machine/m2comm.cpp                        |   44 +-
 src/mame/machine/m2comm.h                          |   18 +-
 src/mame/machine/mcr68.cpp                         |  500 +-----
 src/mame/machine/midwayic.cpp                      |  106 +-
 src/mame/machine/midwayic.h                        |   45 +-
 src/mame/machine/midwunit.cpp                      |   16 +-
 src/mame/machine/naomigd.cpp                       |   80 +-
 src/mame/machine/nl_hazelvid.cpp                   |  241 +++
 src/mame/machine/nl_hazelvid.h                     |    4 +
 src/mame/machine/nycaptor.cpp                      |    2 +-
 src/mame/machine/pitnrun.cpp                       |    2 +-
 src/mame/machine/seibucop/seibucop.cpp             |    2 -
 src/mame/machine/seibucop/seibucop_dma.hxx         |   39 +-
 src/mame/machine/slapfght.cpp                      |  141 +-
 src/mame/machine/theglobp.cpp                      |  258 ---
 src/mame/machine/tnzs.cpp                          |  599 ++-----
 src/mame/machine/toaplan1.cpp                      |  139 --
 src/mame/machine/xbox.cpp                          |  101 +-
 src/mame/machine/xbox_usb.cpp                      |    2 +-
 src/mame/mame.lst                                  |   78 +-
 src/mame/mess.flt                                  |    3 +
 src/mame/nl.lst                                    |    2 +
 src/mame/video/4enraya.cpp                         |    2 +-
 src/mame/video/beezer.cpp                          |   75 -
 src/mame/video/eolith.cpp                          |    2 +-
 src/mame/video/fcombat.cpp                         |    2 +-
 src/mame/video/finalizr.cpp                        |   14 +-
 src/mame/video/freekick.cpp                        |    2 +-
 src/mame/video/fromance.cpp                        |   39 +-
 src/mame/video/homerun.cpp                         |    2 +-
 src/mame/video/k053246_k053247_k055673.cpp         |    8 +-
 src/mame/video/k054156_k054157_k056832.cpp         |   32 +-
 src/mame/video/konamigx.cpp                        |   15 +-
 src/mame/video/ksayakyu.cpp                        |    2 +-
 src/mame/video/ladyfrog.cpp                        |    2 +-
 src/mame/video/leland.cpp                          |   22 +
 src/mame/video/m58.cpp                             |   10 +-
 src/mame/video/mcr68.cpp                           |  175 --
 src/mame/video/mustache.cpp                        |   14 +-
 src/mame/video/nycaptor.cpp                        |    2 +-
 src/mame/video/phoenix.cpp                         |   14 +-
 src/mame/video/pitnrun.cpp                         |    2 +-
 src/mame/video/pk8000.cpp                          |   90 +-
 src/mame/video/rltennis.cpp                        |    2 +-
 src/mame/video/shootout.cpp                        |    4 +-
 src/mame/video/sidepckt.cpp                        |   36 +-
 src/mame/video/ssrj.cpp                            |    2 +-
 src/mame/video/taito_o.cpp                         |    2 +-
 src/mame/video/tecmo_mix.cpp                       |   45 +-
 src/mame/video/tecmo_mix.h                         |    6 +-
 src/mame/video/tnzs.cpp                            |   11 +-
 src/mame/video/{chihiro.cpp => xbox_nv2a.cpp}      |  281 ++-
 src/mame/video/yunsung8.cpp                        |   40 +-
 src/osd/modules/debugger/debugimgui.cpp            |    9 +-
 src/osd/modules/debugger/debugqt.cpp               |   16 +-
 src/osd/modules/debugger/qt/breakpointswindow.cpp  |    4 +-
 src/osd/modules/debugger/qt/breakpointswindow.h    |    4 +-
 src/osd/modules/debugger/qt/dasmwindow.cpp         |    4 +-
 src/osd/modules/debugger/qt/dasmwindow.h           |    4 +-
 .../debugger/qt/deviceinformationwindow.cpp        |    4 +-
 .../modules/debugger/qt/deviceinformationwindow.h  |    4 +-
 src/osd/modules/debugger/qt/deviceswindow.cpp      |    4 +-
 src/osd/modules/debugger/qt/deviceswindow.h        |    4 +-
 src/osd/modules/debugger/qt/logwindow.cpp          |    4 +-
 src/osd/modules/debugger/qt/logwindow.h            |    4 +-
 src/osd/modules/debugger/qt/mainwindow.cpp         |    4 +-
 src/osd/modules/debugger/qt/mainwindow.h           |    4 +-
 src/osd/modules/debugger/qt/memorywindow.cpp       |    4 +-
 src/osd/modules/debugger/qt/memorywindow.h         |    4 +-
 src/osd/modules/debugger/qt/windowqt.cpp           |    4 +-
 src/osd/modules/debugger/qt/windowqt.h             |    4 +-
 src/osd/modules/debugger/win/editwininfo.cpp       |   88 +-
 src/osd/modules/debugger/win/editwininfo.h         |   27 +-
 src/osd/modules/font/font_dwrite.cpp               |   60 +-
 src/osd/modules/lib/osdlib.h                       |   26 +
 src/osd/modules/lib/osdlib_uwp.cpp                 |  212 ---
 src/osd/modules/monitor/monitor_dxgi.cpp           |   15 +-
 src/osd/modules/render/bgfx/shaders/makefile       |    2 +-
 src/osd/modules/render/d3d/d3dhlsl.cpp             |   26 +-
 src/osd/modules/render/d3d/d3dhlsl.h               |    5 +-
 src/osd/modules/sound/xaudio2_sound.cpp            |   20 +-
 src/osd/uwp/uwpcompat.cpp                          |   13 +-
 src/osd/uwp/uwpcompat.h                            |    4 +-
 src/tools/imgtool/imgtool.cpp                      |   39 +-
 src/tools/imgtool/imgtool.h                        |   17 +-
 src/tools/imgtool/main.cpp                         |   35 +-
 src/tools/imgtool/stream.cpp                       |   27 +-
 src/tools/imgtool/stream.h                         |    5 +-
 uismall.bdf                                        |    7 +-
 whatsnew.txt                                       |  730 ++++----
 652 files changed, 29594 insertions(+), 15628 deletions(-)

diff --git a/3rdparty/lua-zlib/lua_zlib.c b/3rdparty/lua-zlib/lua_zlib.c
index 3c26793..e70c85c 100644
--- a/3rdparty/lua-zlib/lua_zlib.c
+++ b/3rdparty/lua-zlib/lua_zlib.c
@@ -392,7 +392,7 @@ LUALIB_API int luaopen_zlib(lua_State * const L) {
 
     SETLITERAL("_COPYRIGHT", "Copyright (c) 2009-2010 Brian Maher");
     SETLITERAL("_DESCRIPTION", "Yet another binding to the zlib library");
-    SETLITERAL("_VERSION", "lua-zlib $Id: b619258c75f480717fad20c113c3b1a35f888ce0 $  (tag: mame0180)");
+    SETLITERAL("_VERSION", "lua-zlib $Id: b619258c75f480717fad20c113c3b1a35f888ce0 $  (tag: mame0181)");
 
     /* Expose this to lua so we can do a test: */
     SETINT("_TEST_BUFSIZ", LUAL_BUFFERSIZE);
diff --git a/android-project/app/src/main/AndroidManifest.xml b/android-project/app/src/main/AndroidManifest.xml
index e2aa57f..e438149 100644
--- a/android-project/app/src/main/AndroidManifest.xml
+++ b/android-project/app/src/main/AndroidManifest.xml
@@ -4,8 +4,8 @@
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
       package="org.mamedev.mame"
-      android:versionCode="180"
-      android:versionName="0.180"
+      android:versionCode="181"
+      android:versionName="0.181"
       android:installLocation="auto">
 
     <!-- Android 5.0 -->
diff --git a/hash/a7800.xml b/hash/a7800.xml
index 748672a..bf24518 100644
--- a/hash/a7800.xml
+++ b/hash/a7800.xml
@@ -1806,7 +1806,7 @@ almost nothing like the prototype.
 		<info name="serial" value="CX7816"/>
 		<sharedfeat name="compatibility" value="NTSC"/>
 		<part name="cart" interface="a7800_cart">
-			<feature name="slot" value="a78_sg_ram" />
+			<feature name="slot" value="a78_mram" />
 			<dataarea name="rom" size="32768">
 				<rom name="rescuefr.bin" size="32768" crc="9a74fbf2" sha1="6653022f38e553d475896a918850158eaf8f77ff" offset="0" />
 			</dataarea>
diff --git a/hash/apple1.xml b/hash/apple1.xml
index 8991c79..ce222b9 100644
--- a/hash/apple1.xml
+++ b/hash/apple1.xml
@@ -94,10 +94,10 @@
 		<year>1976</year>
 		<publisher>apple computer inc</publisher>
 			<!-- P/N A1T008X-->
-		<info name="usage" value="Load at 800.09FFR, enter at 0800R" />
+		<info name="usage" value="Load at 800.09FFR, enter at 09F0R" />
 		<part name="cass" interface="apple1_cass">
-			<dataarea name="cass" size="1393604">
-				<rom name="dis-assembler.wav" size="1393604" crc="a49c7474" sha1="1722bada9de231b90233c8aafe474e9c738366e8" offset="0" />
+			<dataarea name="cass" size="1905164">
+				<rom name="dis-assembler.wav" size="1905164" crc="3fb58ea4" sha1="194829241eec0e418469e1fc8e92d5a2721dcb6d" offset="0" />
 			</dataarea>
 		</part>
 	</software>
diff --git a/hash/apple2.xml b/hash/apple2.xml
index f067f59..84b0993 100644
--- a/hash/apple2.xml
+++ b/hash/apple2.xml
@@ -3082,7 +3082,7 @@
 	</software>
 
 	<software name="captckoo">
-		<description>Captain Cuckoo</description>
+		<description>Captain Cuckoo (cracked)</description>
 		<year>1984</year>
 		<publisher>Kurt and Yan Software</publisher>
 
diff --git a/hash/apricot_flop.xml b/hash/apricot_flop.xml
new file mode 100644
index 0000000..41ecc4c
--- /dev/null
+++ b/hash/apricot_flop.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0"?>
+<!DOCTYPE softwarelist SYSTEM "softwarelist.dtd">
+
+<softwarelist name="apricot_flop" description="ACT Apricot PC/Xi floppy disks">
+
+	<!-- MS-DOS 2.00 BIOS VR1.4 -->
+	<software name="demopics">
+		<description>Demonstration Pictures</description>
+		<year>1984</year>
+		<publisher>ACT</publisher>
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="307631">
+				<rom name="demopics.dsk" size="307631" crc="7db75019" sha1="2b8f002588304c5ef23c13c9be9c167a7ceed0c9" offset="0"/>
+			</dataarea>
+		</part>
+	</software>
+
+	<!-- 20 Feb 85 -->
+	<software name="dos211_27">
+		<description>MS-DOS 2.11 BIOS VR2.7</description>
+		<year>1985</year>
+		<publisher>ACT</publisher>
+		<part name="flop1" interface="floppy_3_5">
+			<feature name="part_id" value="Disk 1 (Manager & Tools)" />
+			<dataarea name="flop" size="322937">
+				<rom name="1pcxu04p.dsk" size="322937" crc="cfe455a9" sha1="4f8ccfbe1161404a47d309bd139d321fb0013a1a" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_3_5">
+			<feature name="part_id" value="Disk 2 (Disk & Editors)" />
+			<dataarea name="flop" size="321919">
+				<rom name="2pcxu04p.dsk" size="321919" crc="22a234ca" sha1="85a3a8d19f2d5357ac71ce8bbacf9512e93bed62" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop3" interface="floppy_3_5">
+			<feature name="part_id" value="Disk 3 (SuperWriter)" />
+			<dataarea name="flop" size="277127">
+				<rom name="3pcxu04p.dsk" size="277127" crc="75f9f57d" sha1="40f083ab4a68d213635cc5c2ebb6cb8b202c6514" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop4" interface="floppy_3_5">
+			<feature name="part_id" value="Disk 4 (Async & MS-Basic)" />
+			<dataarea name="flop" size="279672">
+				<rom name="4pcxu04p.dsk" size="279672" crc="e1c34b89" sha1="84765d86784742ff1efc8f8fe4101d08703ea291" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop5" interface="floppy_3_5">
+			<feature name="part_id" value="Disk 5 (SuperCalc & SuperPlanner)" />
+			<dataarea name="flop" size="223173">
+				<rom name="5pcxu04p.dsk" size="223173" crc="ffc21ff2" sha1="0e332002f5be5e38b83f36789baac03b24289121" offset="0"/>
+			</dataarea>
+		</part>
+	</software>
+
+	<!-- 17 Oct 85 -->
+	<software name="dos211_31">
+		<description>MS-DOS 2.11 BIOS VR3.1</description>
+		<year>1985</year>
+		<publisher>ACT</publisher>
+		<part name="flop1" interface="floppy_3_5">
+			<feature name="part_id" value="Disk 1 (Activity & Tutor)" />
+			<dataarea name="flop" size="326512">
+				<rom name="1pcxeu03p.dsk" size="326512" crc="a54c009f" sha1="85c6426042c5ac37a60e05eddcf499e71d051db6" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_3_5">
+			<feature name="part_id" value="Disk 2 (Activity & Editors)" />
+			<dataarea name="flop" size="326513">
+				<rom name="2pcxeu03p.dsk" size="326513" crc="339a564a" sha1="e86466629af63f102568e80ddc924ba291e0ca5d" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop3" interface="floppy_3_5">
+			<feature name="part_id" value="Disk 3 (Async & Diary)" />
+			<dataarea name="flop" size="295460">
+				<rom name="3pcxeu03p.dsk" size="295460" crc="623b99e9" sha1="8c443772dcbbebb322abc5574605bdedac755266" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop4" interface="floppy_3_5">
+			<feature name="part_id" value="Disk 4 (GW-Basic & Sketch)" />
+			<dataarea name="flop" size="267468">
+				<rom name="4pcxeu03p.dsk" size="267468" crc="010b8617" sha1="b17692f58ed9060e5af25268e84d39695b3bbd1e" offset="0"/>
+			</dataarea>
+		</part>
+	</software>
+
+	<!-- MS-DOS 2.11 BIOS VR2.4 -->
+	<software name="quest">
+		<description>QUEST - The Adventure</description>
+		<year>1984</year>
+		<publisher>Quest Automation Ltd</publisher>
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="324909">
+				<rom name="quest.dsk" size="324909" crc="df11c592" sha1="989dc29d1dead78452b5b0afb9591356484c643d" offset="0"/>
+			</dataarea>
+		</part>
+	</software>
+
+</softwarelist>
diff --git a/hash/hp_ipc.xml b/hash/hp_ipc.xml
new file mode 100644
index 0000000..b5f64a9
--- /dev/null
+++ b/hash/hp_ipc.xml
@@ -0,0 +1,461 @@
+<?xml version="1.0"?>
+<!DOCTYPE softwarelist SYSTEM "softwarelist.dtd">
+<softwarelist name="hp_ipc" description="HP Integral PC diskettes">
+
+	<software name="memomakr">
+		<description>MemoMaker for Integral</description>
+		<year>1984</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="652950">
+				<rom name="ipcmemom.td0" size="652950" crc="41dd72a2" sha1="1bd3dde57a83a09dbd8ad2f18e52f7d96ee45f63" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="multipln">
+		<description>Multiplan for Integral</description>
+		<year>1984</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="172162">
+				<rom name="multipl.td0" size="172162" crc="e8e929d7" sha1="2ddbab7b6683fd2ba30238fb013ff2f25c1bcdd7" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="basic_r5">
+		<description>Integral BASIC Release 5</description>
+		<year>1984</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="602609">
+				<rom name="intbasic.td0" size="602609" crc="49a70601" sha1="f884a3ff678b57167451a269d1b551374614f679" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="datacomm">
+		<description>Datacomm r1.0.1</description>
+		<year>1984</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="220544">
+				<rom name="ipcdatac.td0" size="220544" crc="97c35bcb" sha1="a4e006459b24400383c2e136645ae5ab863e7483" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="ipccdoc">
+		<description>C Language 1of3 (docs)</description>
+		<year>1984</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="456537">
+				<rom name="ipccdoc.td0" size="456537" crc="5c90332c" sha1="1f1a971e99d929a45d28654d6c32dbfeb20feb4d" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="ipccprep">
+		<description>C Language 2of3 (preprocessor)</description>
+		<year>1984</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="554063">
+				<rom name="ipccprep.td0" size="554063" crc="f80fb865" sha1="547aa6174d4c0e08cc9005bb3c59fc88c288c8a1" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="ipcctran">
+		<description>C Language 3of3 (translator)</description>
+		<year>1984</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="452140">
+				<rom name="ipcctran.td0" size="452140" crc="ef2494e0" sha1="ffd764fd701f4ffe896b919b18dc3474eff95f2a" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="basicut">
+		<description>HP-UX BASIC Utilities for Integral</description>
+		<year>1985</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="218967">
+				<rom name="basicut.td0" size="218967" crc="bd92ec7a" sha1="611eea08494ce123052453cd8cf45ce6fcc3e09f" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="ipcforut">
+		<description>FORTRAN r5.0.0 1of2 (utilities)</description>
+		<year>1985</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="581442">
+				<rom name="ipcforut.td0" size="581442" crc="fb7c2093" sha1="2d8492a8c74e06c405998d848826a4fd139cf6fe" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="ipcforcp">
+		<description>FORTRAN r5.0.0 2of2 (translator)</description>
+		<year>1985</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="549753">
+				<rom name="ipcforcp.td0" size="549753" crc="a4a8c914" sha1="ec76c80f81e0b55843ff4028baacb0137b94ec84" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="lisppilt">
+		<description>LISP and PILOT Languages</description>
+		<year>1985</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="565866">
+				<rom name="lisppilt.td0" size="565866" crc="096d357b" sha1="3c4cbd4ddbb39ff02e0844ab5de36f1aaa418598" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="tksolve">
+		<description>Tk!Solver</description>
+		<year>1985</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="190676">
+				<rom name="tksolve.td0" size="190676" crc="76d7752e" sha1="024ae038239c651898e9df62ce8a1256a73ea542" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="diagpgrm">
+		<description>Diagraph for Integral 1of2 (program)</description>
+		<year>1985</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="634074">
+				<rom name="diagpgrm.td0" size="634074" crc="7963e6fa" sha1="e9b65d758fbb9d5d68b21d5fb05dcd72c8d38f0e" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="diagsymb">
+		<description>Diagraph for Integral 2of2 (symbols)</description>
+		<year>1985</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="690608">
+				<rom name="diagsymb.td0" size="690608" crc="8f038cd1" sha1="5006444a81ac785db5e448a63c741ab3218084ea" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="microtrk">
+		<description>MicroTrak v1.4f</description>
+		<year>1985</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="111659">
+				<rom name="ipcmictk.td0" size="111659" crc="6be07a20" sha1="4d0a60c1bd2e7c83b648270154d5c6fed8b2696a" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="ipcpascp">
+		<description>PASCAL v5.0 1of2 (compiler)</description>
+		<year>1985</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="670738">
+				<rom name="ipcpascp.td0" size="670738" crc="3c33177e" sha1="37f9a461d15961b436fddc6890710005a7438c5c" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="ipcpasdc">
+		<description>PASCAL v5.0 2of2 (docs)</description>
+		<year>1985</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="557887">
+				<rom name="ipcpasdc.td0" size="557887" crc="873b0f30" sha1="aa1e9c73b213780862567eced9073a843900304f" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="ipcforth">
+		<description>FORTH v1.0 for Integral</description>
+		<year>1985</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="296521">
+				<rom name="ipcforth.td0" size="296521" crc="13b25447" sha1="bb8f08a8247ad5d6743832d949bf19fb789b0aac" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="tutor">
+		<description>Utility Discs for Integral 1of6 (Tutor)</description>
+		<year>1985</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="404018">
+				<rom name="tutor.td0" size="404018" crc="c5af6ff5" sha1="47eb431f609fcc6f87d3a7b5c9cafb7f9c232135" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="utilitie">
+		<description>Utility Discs for Integral 2of6 (Utilities)</description>
+		<year>1985</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="571098">
+				<rom name="utilitie.td0" size="571098" crc="1f9420ad" sha1="97ef267109214f2bdc183032f4d87bd1cc0e7be3" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="diagnstc">
+		<description>Utility Discs for Integral 3of6 (Diagnostic)</description>
+		<year>1985</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="206296">
+				<rom name="diagnstc.td0" size="206296" crc="e3b7461e" sha1="276f82b1b4cc1bb4cf8a40311afa3ee15716004c" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="sysmdisc">
+		<description>Utility Discs for Integral 4of6 (System Disc)</description>
+		<year>1985</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="325235">
+				<rom name="sysmdisc.td0" size="325235" crc="5773decd" sha1="46a23f0fb2c4ea9b738ee68390bb349dd738ae6b" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="hp_ux1">
+		<description>Utility Discs for Integral 5of6 (HP-UX Commands 1)</description>
+		<year>1985</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="626512">
+				<rom name="hp-ux1.td0" size="626512" crc="cf5da5fa" sha1="4bde09a9d37f5f8f6e55925f2428c342d95db19c" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="hp_ux2">
+		<description>Utility Discs for Integral 6of6 (HP-UX Commands 2)</description>
+		<year>1985</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="648152">
+				<rom name="hp-ux2.td0" size="648152" crc="9f843794" sha1="de4b2276aba66d4c28e9bb44db60c62472ec6441" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="intgame1">
+		<description>Integral Games 1of3</description>
+		<year>1985</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="683944">
+				<rom name="intgame1.td0" size="683944" crc="f142dece" sha1="a6436079839667456be5f7dfd05978b1c7290d71" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="intgame2">
+		<description>Integral Games 2of3</description>
+		<year>1985</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="389053">
+				<rom name="intgame2.td0" size="389053" crc="8e4b6266" sha1="3a5727367f580a4d8b2109ba880147f5c3025d62" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="intgame3">
+		<description>Integral Games 3of3</description>
+		<year>1985</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="184147">
+				<rom name="intgame3.td0" size="184147" crc="a78f471d" sha1="9020b09ee1a256b2d085cc886d5998e2b2dc9d23" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="inthack">
+		<description>Hack 3.0.2 for Integral</description>
+		<year>1985</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="548830">
+				<rom name="inthack.td0" size="548830" crc="6a371529" sha1="de37526aabfc4c326a3bd89a0f5b5d9fd830b915" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="plotrack">
+		<description>PlotTrack Rev 1.2b</description>
+		<year>1986</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="297583">
+				<rom name="plotrack.td0" size="297583" crc="b9b5975c" sha1="1a315b196cd353e1d2d79a5e8b84e935b8f99a72" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="ipcromtl">
+		<description>EPROM/ROM Tools r5.0</description>
+		<year>1986</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="400488">
+				<rom name="ipcromtl.td0" size="400488" crc="1c302801" sha1="8341446066be25649357614dd4aa937eb66f118e" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="ipcapl">
+		<description>APL Plus v3.0 1of2</description>
+		<year>1986</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="486723">
+				<rom name="ipcapl.td0" size="486723" crc="1413db63" sha1="9b6e7f5f6fa66ecfad4071fd460b0faa20eb06ca" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="ipcaplw">
+		<description>APL Plus v3.0 2of2</description>
+		<year>1986</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="381652">
+				<rom name="ipcaplw.td0" size="381652" crc="ede2be4d" sha1="8f85f6e4e4238fa9f21efc3beea82860157884ee" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="ipctranu">
+		<description>PC File Translation Utilities</description>
+		<year>1986</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="641077">
+				<rom name="ipctranu.td0" size="641077" crc="6d3d5de7" sha1="b1b27f9846544dbcaa8442140bdad7b29c61fcc0" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="ipcsuput">
+		<description>Super Utilities (LIF format file!)</description>
+		<year>1986</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="587264">
+				<rom name="ipcsuput.td0" size="587264" crc="15a881cd" sha1="c4673a2f7188ea0b29b8a4d9bd4a60856ed8f3d2" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="ipcart">
+		<description>Graphics, Text and Misc Utilities</description>
+		<year>1987</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="534655">
+				<rom name="ipcart.td0" size="534655" crc="fc6070bc" sha1="794216f066e1ae77c4d331b5cdb66c7735fffeaf" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="ipcbasbn">
+		<description>BASIC Bonus Disc</description>
+		<year>1987</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="413321">
+				<rom name="ipcbasbn.td0" size="413321" crc="b6d8f987" sha1="3bce09a5e53e64f0ad602b67016b035f1266b910" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="ipcdwd">
+		<description>Driver Writers Disc</description>
+		<year>1987</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="641039">
+				<rom name="ipcdwd.td0" size="641039" crc="1e604853" sha1="ac5d69917a026a70ce8142d12a401279e627554c" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="ipcmandl">
+		<description>Mandelbrot</description>
+		<year>1988</year>
+		<publisher>???</publisher>
+
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="285987">
+				<rom name="ipcmandl.td0" size="285987" crc="e31c0a41" sha1="59045fcecc336b048595d589815cfb301c594389" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+</softwarelist>
diff --git a/hash/ibm5150.xml b/hash/ibm5150.xml
index d2a2ccc..b63298b 100644
--- a/hash/ibm5150.xml
+++ b/hash/ibm5150.xml
@@ -64,29 +64,6 @@ Known PC Booter Games Not Dumped, Or Dumped and Lost when Demonlord's Site went
 -->
 <softwarelist name="ibm5150" description="IBM PC disk images">
 
-	<!-- Operating Systems -->
-	<software name="pcdos10">
-		<description>PC DOS 1.0</description>
-		<year>1981</year>
-		<publisher>IBM</publisher>
-		<part name="flop1" interface="floppy_5_25">
-			<dataarea name="flop" size="163840">
-				<rom name="pcdos100.img" size="163840" crc="2df1c1c8" sha1="7d3e3a807ad2144315b3c3b90751ff691d3895db" offset="0" />
-			</dataarea>
-		</part>
-	</software>
-
-	<software name="pcdos110">
-		<description>PC DOS 1.10</description>
-		<year>1982</year>
-		<publisher>IBM</publisher>
-		<part name="flop1" interface="floppy_5_25">
-			<dataarea name="flop" size="163840">
-				<rom name="ibmdos11.img" size="163840" crc="ddfe9550" sha1="437bec5be7d28cc2248d5477f38a07545816e49a" offset="0" />
-			</dataarea>
-		</part>
-	</software>
-
 	<!-- Booter Games -->
 	<software name="3ktrivia">
 		<description>3-K Trivia</description>
@@ -2626,6 +2603,17 @@ Known PC Booter Games Not Dumped, Or Dumped and Lost when Demonlord's Site went
 		</part>
 	</software>
 
+	<software name="jingdisk">
+		<description>Jingle Disk</description>
+		<year>1986</year>
+		<publisher>ThoughtWare</publisher>
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size = "184320">
+				<rom name="Disk01.img" size="184320" crc="55dd837c" sha1="fab48e2f3153d8529406e1c0e0428dd32e069618" offset="0"/>
+			</dataarea>
+		</part>
+	</software>
+
 	<software name="visicalc">
 		<description>VisiCalc</description>
 		<year>1982</year>
@@ -2702,277 +2690,1136 @@ Known PC Booter Games Not Dumped, Or Dumped and Lost when Demonlord's Site went
 		</part>
 	</software>
 
-	<!-- SDK -->
+	<software name="msword1d">
+		<description>Word (PC World Demo)</description>
+		<year>1983</year>
+		<publisher>Microsoft</publisher>
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size = "163840">
+				<rom name="worddemo.img" size="163840" crc="c3004ad2" sha1="24b4d7894bbfa335de49f968c86758f43a82a00c" offset="0"/>
+			</dataarea>
+		</part>
+	</software>
 
-	<software name="win13sdk">
-		<description>Windows 1.03 SDK</description>
+	<software name="msword3">
+		<description>Word 3.0 (6-23-86)</description>
 		<year>1986</year>
 		<publisher>Microsoft</publisher>
-
+		<info name="version" value="3.00" />
 		<part name="flop1" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="utilities disk 1 (050-150-078).img" size="368640" crc="f2675ca3" sha1="352eb818acaf30119309300399c2acc9433efb8d" offset="0" />
+			<dataarea name="flop" size = "368640">
+				<rom name="Disk01.img" size="368640" crc="5b63c742" sha1="3a981e0a6835b9a2d1f3db40a53b20d1815264d7" offset="0"/>
 			</dataarea>
 		</part>
 		<part name="flop2" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="utilities disk 2 (050-150-079).img" size="368640" crc="96264321" sha1="fd34ac2c00f5d44aedf9f9a11fc54439450cfd7f" offset="0" />
+			<dataarea name="flop" size = "368640">
+				<rom name="Disk02.img" size="368640" crc="8f164895" sha1="b552d0164babca85e10d9eb0eb287ebaabf63e96" offset="0"/>
 			</dataarea>
 		</part>
 		<part name="flop3" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="libraries and include files disk (c) (050-150-080).img" size="368640" crc="34478d1b" sha1="334134cd115cbae61603776bf16e86066a3f0dc6" offset="0" />
+			<dataarea name="flop" size = "368640">
+				<rom name="Disk03.img" size="368640" crc="ad890b26" sha1="99a37abd36ae8f016bd54d3bb0ab3b3a1ed5983b" offset="0"/>
 			</dataarea>
 		</part>
 		<part name="flop4" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="libraries, include files, and sample source disk (pascal) (050-150-081).img" size="368640" crc="f3004306" sha1="affaeff13576e4f451a21c1bf3b39a8f475039c0" offset="0" />
+			<dataarea name="flop" size = "368640">
+				<rom name="Disk04.img" size="368640" crc="f4dafa3b" sha1="e788f8f9778ea97a556fe4f14ab0a684bf7ab6c8" offset="0"/>
 			</dataarea>
 		</part>
 		<part name="flop5" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="symbol and debug libraries (050-150-082).img" size="368640" crc="2f58fe8d" sha1="7682ce2d95372735f1d20776e5024faa0db25369" offset="0" />
+			<dataarea name="flop" size = "368640">
+				<rom name="Disk05.img" size="368640" crc="0428a8c5" sha1="8390cf8b728fbad8f8c7c0908d2208379afd358a" offset="0"/>
 			</dataarea>
 		</part>
 		<part name="flop6" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="sample source code disk 1 (050-150-083).img" size="368640" crc="27a18dcd" sha1="2fcd89cd8239ba5435b754c3ff1b653461143c8e" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop7" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="sample source code disk 2 (050-150-084).img" size="368640" crc="8e762502" sha1="540e0a40059a25f5c16a8545e65421a9d0febdf8" offset="0" />
+			<dataarea name="flop" size = "368640">
+				<rom name="Disk06.img" size="368640" crc="4c9b966b" sha1="caad8e07790a85db5c89831b25ccc5b941ea741f" offset="0"/>
 			</dataarea>
 		</part>
 	</software>
 
-	<!-- OS -->
-
-	<software name="cpm8610">
-		<description>CP/M-86 for the IBM Personal Computer (Version 1.0)</description>
-		<year>1982</year>
-		<publisher>Digital Research</publisher>
-		<info name="version" value="1.0" />
+	<software name="msword3a" cloneof="msword3">
+		<description>Word 3.0 (4-10-86)</description>
+		<year>1986</year>
+		<publisher>Microsoft</publisher>
+		<info name="version" value="3.00" />
 		<part name="flop1" interface="floppy_5_25">
-			<dataarea name="flop" size="163840">
-				<rom name="cpm86.img" size="163840" crc="79c8ef92" sha1="f4074a4b2f5826faa893869b163461a8808d13ef" offset="0" />
+			<dataarea name="flop" size = "368640">
+				<rom name="Disk01a.img" size="368640" crc="058ae09c" sha1="4cc7d7c4c0ec84c1854f50cb22f2989e3a5d6005" offset="0"/>
 			</dataarea>
 		</part>
-	</software>
-
-	<software name="cpm8611">
-		<description>CP/M-86 for the IBM Personal Computer (Version 1.1)</description>
-		<year>1982</year>
-		<publisher>Digital Research</publisher>
-		<info name="version" value="1.1" />
-		<part name="flop1" interface="floppy_5_25">
-			<dataarea name="flop" size="109434">
-				<rom name="cpm8611.td0" size="109434" crc="c1b7a3f9" sha1="28c3e3edc9698680a63e0fa9ce6d58d6829fdc68" offset="0" />
+		<part name="flop2" interface="floppy_5_25">
+			<dataarea name="flop" size = "368640">
+				<rom name="Disk02.img" size="368640" crc="8f164895" sha1="b552d0164babca85e10d9eb0eb287ebaabf63e96" offset="0"/>
 			</dataarea>
 		</part>
-	</software>
-
-	<software name="ecpm8611">
-		<description>Eagle CP/M-86 (Version 1.1B)</description>
-		<year>1983</year>
-		<publisher>Digital Research</publisher>
-		<info name="version" value="1.1B" />
-		<part name="flop1" interface="floppy_5_25">
-			<dataarea name="flop" size="327680">
-				<rom name="cpm86-disk1.dsk" size="327680" crc="585295a0" sha1="4d026fcc175c79ffff190dce3182815944c122f3" offset="0" />
+		<part name="flop3" interface="floppy_5_25">
+			<dataarea name="flop" size = "368640">
+				<rom name="Disk03.img" size="368640" crc="ad890b26" sha1="99a37abd36ae8f016bd54d3bb0ab3b3a1ed5983b" offset="0"/>
 			</dataarea>
 		</part>
-		<part name="flop2" interface="floppy_5_25">
-			<dataarea name="flop" size="327680">
-				<rom name="cpm86-disk2.dsk" size="327680" crc="c780f765" sha1="9a4eafd6f6b7d01d1a39f63d245e0653263de189" offset="0" />
+		<part name="flop4" interface="floppy_5_25">
+			<dataarea name="flop" size = "368640">
+				<rom name="Disk04a.img" size="368640" crc="84d614d6" sha1="e40e0040d5eca604e1ec80eec2e661ba51a0701b" offset="0"/>
 			</dataarea>
 		</part>
-	</software>
-
-	<software name="ibmdos10">
-		<description>IBM Personal Computer DOS (Version 1.00)</description>
-		<year>1981</year>
-		<publisher>IBM</publisher>
-		<info name="version" value="1.00" />
-		<part name="flop1" interface="floppy_5_25">
-			<dataarea name="flop" size="163840">
-				<rom name="ibmdos 1.00.img" size="163840" crc="2df1c1c8" sha1="7d3e3a807ad2144315b3c3b90751ff691d3895db" offset="0" />
+		<part name="flop5" interface="floppy_5_25">
+			<dataarea name="flop" size = "368640">
+				<rom name="Disk05.img" size="368640" crc="0428a8c5" sha1="8390cf8b728fbad8f8c7c0908d2208379afd358a" offset="0"/>
 			</dataarea>
 		</part>
-	</software>
-
-	<software name="ibmdos11">
-		<description>IBM Personal Computer DOS (Version 1.10)</description>
-		<year>1982</year>
-		<publisher>IBM</publisher>
-		<info name="version" value="1.10" />
-		<part name="flop1" interface="floppy_5_25">
-			<dataarea name="flop" size="163840">
-				<rom name="ibmdos 1.10.img" size="163840" crc="ddfe9550" sha1="437bec5be7d28cc2248d5477f38a07545816e49a" offset="0" />
+		<part name="flop6" interface="floppy_5_25">
+			<dataarea name="flop" size = "368640">
+				<rom name="Disk06a.img" size="368640" crc="b237925e" sha1="0716511c4084fe8a43b771e90a9b99f9bd9263df" offset="0"/>
 			</dataarea>
 		</part>
 	</software>
 
-	<software name="ibmdos2">
-		<description>IBM Personal Computer DOS (Version 2.0)</description>
-		<year>1983</year>
-		<publisher>IBM</publisher>
-		<info name="version" value="2.0" />
+	<software name="msword3dem" cloneof="msword3">
+		<description>Word 3.0 Demonstration</description>
+		<year>1986</year>
+		<publisher>Microsoft</publisher>
+		<info name="version" value="3.00" />
 		<part name="flop1" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="ibmdos 2.img" size="368640" crc="d0fb7d31" sha1="cbee7f6109fb0ed8a94de1893fc47ab066de36d3" offset="0" />
+			<dataarea name="flop" size = "368640">
+				<rom name="MS Word 3.0 preview.img" size="368640" crc="31c38dd9" sha1="dbcd579164186a317cf70f3ecb6c092a32c888c1" offset="0"/>
 			</dataarea>
 		</part>
 	</software>
 
-	<software name="ibmdos2a">
-		<description>IBM Personal Computer DOS (Version 2.0, Alt)</description>
-		<year>1983</year>
-		<publisher>IBM</publisher>
-		<info name="version" value="2.0" />
+	<software name="msword31">
+		<description>Word 3.1 (5.25")</description>
+		<year>1986</year>
+		<publisher>Microsoft</publisher>
+		<info name="version" value="3.10" />
 		<part name="flop1" interface="floppy_5_25">
-			<dataarea name="flop" size="184320">
-				<rom name="ibmdos 2 (disk 1).img" size="184320" crc="b8f8ce15" sha1="e4478aeece1aa1627ac595e5fca96fbd8ad562c7" offset="0" />
+			<feature name="part_id" value="Word Program" />
+			<dataarea name="flop" size = "368640">
+				<rom name="Disk01.img" size="368640" crc="2ea91be6" sha1="a7a7499c55b527e0d5fe925a04069ffacf060f94" offset="0"/>
 			</dataarea>
 		</part>
 		<part name="flop2" interface="floppy_5_25">
-			<dataarea name="flop" size="184320">
-				<rom name="ibmdos 2 (disk 2).img" size="184320" crc="cf37729c" sha1="4f6fcc26d4382a8fed950bfaa8961669d513f93b" offset="0" />
+			<feature name="part_id" value="Spell Disk" />
+			<dataarea name="flop" size = "368640">
+				<rom name="Disk02.img" size="368640" crc="c18ca306" sha1="c201f9f970fa0f8733a59a6808d244606939fdcb" offset="0"/>
 			</dataarea>
 		</part>
-	</software>
-
-	<software name="ibmdos3">
-		<description>IBM Personal Computer DOS (Version 3.0)</description>
-		<year>1984</year>
-		<publisher>IBM</publisher>
-		<info name="version" value="2.0" />
-		<part name="flop1" interface="floppy_5_25">
-			<dataarea name="flop1" size="368640">
-				<rom name="6322635.img" size="368640" crc="20a3dc1c" sha1="1e7430c57109960fd89d281d24e85a086a8284e4" offset="0" />
+		<part name="flop3" interface="floppy_5_25">
+			<feature name="part_id" value="Thesaurus" />
+			<dataarea name="flop" size = "368640">
+				<rom name="Disk03.img" size="368640" crc="e097dbac" sha1="fe6638c21c6b8a00e5fc69dc15ec21bd3f1ee91e" offset="0"/>
 			</dataarea>
-			<dataarea name="flop2" size="368640">
-				<rom name="6322640.img" size="368640" crc="eb75a4c0" sha1="bdb8528a71ea35cb1d9a0a0f13f8f0b745ca8eb6" offset="0" />
+		</part>
+		<part name="flop4" interface="floppy_5_25">
+			<feature name="part_id" value="Utilities" />
+			<dataarea name="flop" size = "368640">
+				<rom name="Disk04.img" size="368640" crc="6220d6de" sha1="b6cc22cd978c11bc70a1a529801fcf66a3b3f21f" offset="0"/>
 			</dataarea>
 		</part>
-	</software>
-
-	<!-- Dos based Games -->
-
-	<software name="2400ad" supported="no"> <!-- unemulated protection, game needs cracked exe to play ATM  -->
-		<description>2400 A.D.</description>
-		<year>1987</year>
-		<publisher>Origin</publisher>
-		<info name="version" value="1.0" />
-		<part name="flop1" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="2400ad.img" size="368640" crc="bf246734" sha1="a9f0be5fa2a5077375dae572622926bb8aa9e28a" offset="0" />
+		<part name="flop5" interface="floppy_5_25">
+			<feature name="part_id" value="Printers 1" />
+			<dataarea name="flop" size = "368640">
+				<rom name="Disk05.img" size="368640" crc="32cdf3b8" sha1="6cfc7bdf41c636a565cf434ca34631f39e05cdd1" offset="0"/>
 			</dataarea>
 		</part>
-	</software>
-
-	<software name="academy" supported="no">
-		<description>Academy - Tau Ceti 2</description>
-		<year>1987</year>
-		<publisher>CRL Group</publisher>
-		<part name="flop1" interface="floppy_5_25">
+		<part name="flop6" interface="floppy_5_25">
+			<feature name="part_id" value="Printers 2" />
 			<dataarea name="flop" size = "368640">
-				<rom name="Academy - Tau Ceti 2 [1987] [CRL Group] [5.25] [1 of 1].img" size="368640" crc="d9047aa4" sha1="09198868eb826dc1be90b941f66c336d21f5df92" offset="0"/>
+				<rom name="Disk06.img" size="368640" crc="5fdc4f51" sha1="c8847fdfc7b639ece4d37299ed210dd96ed001c2" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop7" interface="floppy_5_25">
+			<feature name="part_id" value="Learn Mouse" />
+			<dataarea name="flop" size = "368640">
+				<rom name="Disk07.img" size="368640" crc="22a7a4b6" sha1="c4b5c2d325a58d4c53fb6b908719142c50c066fa" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop8" interface="floppy_5_25">
+			<feature name="part_id" value="Learn Keyboard" />
+			<dataarea name="flop" size = "368640">
+				<rom name="Disk08.img" size="368640" crc="418bedd0" sha1="171f5c2c504522b1e0949194d69c7cc4acbfb855" offset="0"/>
 			</dataarea>
 		</part>
 	</software>
 
-	<software name="aceoface">
-		<description>Ace of Aces</description>
-		<year>1987</year>
-		<publisher>Accolade</publisher>
-		<info name="developer" value="Artech" />
+	<software name="msword31_35" cloneof="msword31">
+		<description>Word 3.11 (3.5")</description>
+		<year>1986</year>
+		<publisher>Microsoft</publisher>
+		<info name="version" value="3.11" />
 		<part name="flop1" interface="floppy_3_5">
+			<feature name="part_id" value="Program, Thesaurus" />
 			<dataarea name="flop" size = "737280">
-				<rom name="Ace of Aces [Accolade] [1987] [3.5].img" size="737280" crc="9f5d1734" sha1="db70bf0ede554db32c8bf3142b199e627f7ecebd" offset="0"/>
+				<rom name="Program, Thesaurus.img" size="737280" crc="60653d3a" sha1="5870c549bcd4b57c6488fe756251a9de52de2144" offset="0"/>
 			</dataarea>
 		</part>
-	</software>
-
-	<software name="aaow">
-		<description>The Ancient Art of War</description>
-		<year>1984</year>
-		<publisher>Brøderbund Software</publisher>
-		<part name="flop1" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="the ancient art of war.img" size="368640" crc="32699e4b" sha1="f4a021d4bc5a9e61b7036cfcd41a43c2a146ab37" offset="0" />
+		<part name="flop2" interface="floppy_3_5">
+			<feature name="part_id" value="Setup, Utilities, Spell" />
+			<dataarea name="flop" size = "737280">
+				<rom name="Setup, Utilities, Spell.img" size="737280" crc="fd5aab9a" sha1="1695a10e308c8e3cf5e6b35d5f7f4cd962a10c1f" offset="0"/>
 			</dataarea>
 		</part>
-	</software>
-
-	<software name="aaowas">
-		<description>The Ancient Art of War at Sea</description>
-		<year>1987</year>
-		<publisher>Brøderbund Software</publisher>
-		<info name="version" value="1.0" />
-		<part name="flop1" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="the ancient art of war at sea.img" size="368640" crc="e9c9f3af" sha1="379376f6255d24a71dc8d156e580966d067b3a84" offset="0" />
+		<part name="flop3" interface="floppy_3_5">
+			<feature name="part_id" value="Printers" />
+			<dataarea name="flop" size = "737280">
+				<rom name="Printers.img" size="737280" crc="ed9de1d4" sha1="06e10f0b88845ca2aec997d25243d4b72f205802" offset="0"/>
 			</dataarea>
 		</part>
-	</software>
-
-	<software name="aaowasa" cloneof="aaowas">
-		<description>The Ancient Art of War at Sea (Alt)</description>
-		<year>1987</year>
-		<publisher>Brøderbund Software</publisher>
-		<info name="version" value="1.5?" />
-		<part name="flop1" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="the ancient art of war at sea (alt).img" size="368640" crc="ac538af6" sha1="143b797aa13d71af042fa6f4b21679f25338c633" offset="0" />
+		<part name="flop4" interface="floppy_3_5">
+			<feature name="part_id" value="Learning" />
+			<dataarea name="flop" size = "737280">
+				<rom name="Learning.img" size="737280" crc="e05bfc06" sha1="b86dcba316469d864c0761e7a99eddc735516227" offset="0"/>
 			</dataarea>
 		</part>
 	</software>
 
-	<software name="bargames">
-		<description>Bar Games</description>
-		<year>1989</year>
-		<publisher>Accolade</publisher>
+	<software name="msword4">
+		<description>Word 4.0 (5.25")</description>
+		<year>1987</year>
+		<publisher>Microsoft</publisher>
 		<part name="flop1" interface="floppy_5_25">
+			<feature name="part_id" value="Word Program" />
 			<dataarea name="flop" size = "368640">
-				<rom name="Bar Games [Accolade] [1989] [5.25] [1].img" size="368640" crc="deb3e64c" sha1="727ae13bd59b19feee0269e08dc831e1393c4a71" offset="0"/>
+				<rom name="Disk01.img" size="368640" crc="fd013952" sha1="dec5a1dea21472500fc3a3b4264bfc6fbbcc3659" offset="0"/>
 			</dataarea>
 		</part>
 		<part name="flop2" interface="floppy_5_25">
+			<feature name="part_id" value="Spell" />
 			<dataarea name="flop" size = "368640">
-				<rom name="Bar Games [Accolade] [1989] [5.25] [2].img" size="368640" crc="684dbc8b" sha1="667d77f7a441e461160545dfb16602898c2e1b2d" offset="0"/>
+				<rom name="Disk02.img" size="368640" crc="216c9e20" sha1="97304d3278b5131eb353628d38ebf0341af4e6e4" offset="0"/>
 			</dataarea>
 		</part>
-	</software>
-
-	<software name="brdtale">
-		<description>The Bard's Tale - Tales of the Unknown (5.25")</description>
-		<year>1987</year>
-		<publisher>Electronic Arts</publisher>
-		<info name="developer" value="Interplay Productions" />
-		<part name="flop1" interface="floppy_5_25">
-			<feature name="part_id" value="Program Disk" />
+		<part name="flop3" interface="floppy_5_25">
+			<feature name="part_id" value="Thesaurus" />
 			<dataarea name="flop" size = "368640">
-				<rom name="The Bard's Tale 1 - Tales of the Unknown [1987] [5.25] [1 of 2].img" size="368640" crc="40918452" sha1="8cb08b1a090bb7e2b4021a28db27b8f2f9c9df71" offset="0"/>
+				<rom name="Disk03.img" size="368640" crc="3c8f7031" sha1="a144debd293ced7b5a139f617cf2a7019357dcfe" offset="0"/>
 			</dataarea>
 		</part>
-		<part name="flop2" interface="floppy_5_25">
-			<feature name="part_id" value="Picture Disk" />
+		<part name="flop4" interface="floppy_5_25">
+			<feature name="part_id" value="Utilities" />
 			<dataarea name="flop" size = "368640">
-				<rom name="The Bard's Tale 1 - Tales of the Unknown [1987] [5.25] [2 of 2].img" size="368640" crc="a90bd7ec" sha1="68c4d04fb2625766018dcb4a34e27d8348fb817d" offset="0"/>
+				<rom name="Disk04.img" size="368640" crc="d722a2cb" sha1="027cd6936777af5ea490c5d859114e15c50bbf34" offset="0"/>
 			</dataarea>
 		</part>
-	</software>
-
-	<software name="brdtalea" cloneof="brdtale">
-		<description>The Bard's Tale - Tales of the Unknown (5.25", alt)</description>
-		<year>1987</year>
-		<publisher>Electronic Arts</publisher>
-		<info name="developer" value="Interplay Productions" />
-		<part name="flop1" interface="floppy_5_25">
-			<feature name="part_id" value="Program Disk" />
+		<part name="flop5" interface="floppy_5_25">
+			<feature name="part_id" value="Printer 1" />
 			<dataarea name="flop" size = "368640">
-				<rom name="The Bard's Tale 1 - Tales of the Unknown [1987] [5.25] [1 of 2].img" size="368640" crc="40918452" sha1="8cb08b1a090bb7e2b4021a28db27b8f2f9c9df71" offset="0"/>
+				<rom name="Disk05.img" size="368640" crc="8f8567ef" sha1="5db06b563135dd36e15be8d0583990d695f8171f" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop6" interface="floppy_5_25">
+			<feature name="part_id" value="Printer 2" />
+			<dataarea name="flop" size = "368640">
+				<rom name="Disk06.img" size="368640" crc="5417cd99" sha1="1c75513b6e1de5d21422398334445e7943922598" offset="0"/>
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="msword4_35" cloneof="msword4">
+		<description>Word 4.0 (3.5")</description>
+		<year>1987</year>
+		<publisher>Microsoft</publisher>
+		<info name="version" value="4.00" />
+		<part name="flop1" interface="floppy_3_5">
+			<feature name="part_id" value="Program, Thesaurus" />
+			<dataarea name="flop" size = "737280">
+				<rom name="Word 4 disk1.img" size="737280" crc="75d0eb50" sha1="3c8e076682749b1d66a7d9b44f22c76415a7db2b" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_3_5">
+			<feature name="part_id" value="Spell, Utilities" />
+			<dataarea name="flop" size = "737280">
+				<rom name="Word 4 disk2.img" size="737280" crc="ad7ed55b" sha1="85aa0e7785709821b301ecc454dd9f5a4db52e3d" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop3" interface="floppy_3_5">
+			<feature name="part_id" value="Printers" />
+			<dataarea name="flop" size = "737280">
+				<rom name="Word 4 disk3.img" size="737280" crc="4b7e3a41" sha1="cd91bb567b792bcf0e8bcaf1f6876fd18be4c70a" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop4" interface="floppy_3_5">
+			<feature name="part_id" value="Learn disk 1" />
+			<dataarea name="flop" size = "737280">
+				<rom name="Word 4 Learn disk 1.img" size="737280" crc="443ada90" sha1="4e6830b661e62c69ac9f501b45d0dbba8e0db210" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop5" interface="floppy_3_5">
+			<feature name="part_id" value="Learn disk 2" />
+			<dataarea name="flop" size = "737280">
+				<rom name="Word 4 Learn disk 2.img" size="737280" crc="a7a8a3ca" sha1="ccdca131ed512f546289debd308527b390303162" offset="0"/>
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="msword4sv" cloneof="msword4">
+		<description>Word 4.0 (Swedish)</description>
+		<year>1988</year>
+		<publisher>Microsoft</publisher>
+		<part name="flop1" interface="floppy_5_25">
+			<feature name="part_id" value="Programdiskett" />
+			<dataarea name="flop" size = "368640">
+				<rom name="Programdiskett.img" size="368640" crc="7bc313fd" sha1="7d6b956fb04c92a46eeb2a55de272b9cd1190507" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_5_25">
+			<feature name="part_id" value="Stavningsprogram 1" />
+			<dataarea name="flop" size = "368640">
+				<rom name="Stavningsprogram 1.img" size="368640" crc="b3857087" sha1="49577c092e76a880bd1128bccd933d02619ab798" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop3" interface="floppy_5_25">
+			<feature name="part_id" value="Stavningsprogram 2" />
+			<dataarea name="flop" size = "368640">
+				<rom name="Stavningsprogram 2.img" size="368640" crc="da0290d7" sha1="c9c2dcad732e6534211872be4db65892ca8612c9" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop4" interface="floppy_5_25">
+			<feature name="part_id" value="Tilläggsprogram" />
+			<dataarea name="flop" size = "368640">
+				<rom name="Tillaggsprogram.img" size="368640" crc="0018212a" sha1="f241d214f3bfac37392fc6b0ba16582da02f88f0" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop5" interface="floppy_5_25">
+			<feature name="part_id" value="Skrivare 1" />
+			<dataarea name="flop" size = "368640">
+				<rom name="Skrivare 1.img" size="368640" crc="fb7dd96f" sha1="bb8e512c5d25c2827a332803eb3917486ce91a9e" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop6" interface="floppy_5_25">
+			<feature name="part_id" value="Skrivare 2" />
+			<dataarea name="flop" size = "368640">
+				<rom name="Skrivare 2.img" size="368640" crc="cc1b0806" sha1="3f0626794d6607bb3572e749849e8825c3ab50c4" offset="0"/>
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="msword5">
+		<description>Word 5.0</description>
+		<year>1989</year>
+		<publisher>Microsoft</publisher>
+		<part name="flop1" interface="floppy_5_25">
+			<feature name="part_id" value="Program 1" />
+			<dataarea name="flop" size = "368640">
+				<rom name="disk01 - Program 1.img" size="368640" crc="5634fb79" sha1="4c6c734710940c08a6464bb82afb067a9d632ae7" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_5_25">
+			<feature name="part_id" value="Program 2" />
+			<dataarea name="flop" size = "368640">
+				<rom name="disk02 - Program 2.img" size="368640" crc="721e91c5" sha1="c940aa0c841f5569ca9947ced77bd3149eea2533" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop3" interface="floppy_5_25">
+			<feature name="part_id" value="Utilities-Printer" />
+			<dataarea name="flop" size = "368640">
+				<rom name="disk03 - Utilities-Printer.img" size="368640" crc="869653fe" sha1="6a6470ca0e55c2983e9ef7f5fd815f00a2fd7ca7" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop4" interface="floppy_5_25">
+			<feature name="part_id" value="Utilities 1" />
+			<dataarea name="flop" size = "368640">
+				<rom name="disk04 - Utilities 1.img" size="368640" crc="64b00c49" sha1="d95a01cbd4c699a832d4e444ce5fd79c32ea680c" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop5" interface="floppy_5_25">
+			<feature name="part_id" value="Utilities 2" />
+			<dataarea name="flop" size = "368640">
+				<rom name="disk05 - Utilities 2.img" size="368640" crc="187d951f" sha1="dfc03a031cd177d1d9cdb74f0431367f85eabfd2" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop6" interface="floppy_5_25">
+			<feature name="part_id" value="Utilities 3" />
+			<dataarea name="flop" size = "368640">
+				<rom name="disk06 - Utilities 3.img" size="368640" crc="3f1fae7b" sha1="6a07b95892008edcef67f879c8defd0f8979b8c1" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop7" interface="floppy_5_25">
+			<feature name="part_id" value="Spell" />
+			<dataarea name="flop" size = "368640">
+				<rom name="disk07 - Spell.img" size="368640" crc="53d0d240" sha1="e9a0d259e8326f8d17700c9e9067d8e9e6f16b09" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop8" interface="floppy_5_25">
+			<feature name="part_id" value="Thesaurus" />
+			<dataarea name="flop" size = "368640">
+				<rom name="disk08 - Thesaurus.img" size="368640" crc="44c0450b" sha1="1981e687df571c8fa9ddbd9951325fa54c0cecf7" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop9" interface="floppy_5_25">
+			<feature name="part_id" value="Printers 1" />
+			<dataarea name="flop" size = "368640">
+				<rom name="disk09 - Printers 1.img" size="368640" crc="1a035e60" sha1="0613f2ebaf5cfa77400ddd90e8cc1b0c3aa0c6a8" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop10" interface="floppy_5_25">
+			<feature name="part_id" value="Printers 2" />
+			<dataarea name="flop" size = "368640">
+				<rom name="disk10 - Printers 2.img" size="368640" crc="65b305c4" sha1="261df5f3d5ec7c471e8c4a88d2d6c9574811d4cc" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop11" interface="floppy_5_25">
+			<feature name="part_id" value="Learning Word 1" />
+			<dataarea name="flop" size = "368640">
+				<rom name="disk11 - Learning Word 1.img" size="368640" crc="8dcda759" sha1="5e65899af8c481481b46b8505c2a0b96464ca9fb" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop12" interface="floppy_5_25">
+			<feature name="part_id" value="Learning Word 2" />
+			<dataarea name="flop" size = "368640">
+				<rom name="disk12 - Learning Word 2.img" size="368640" crc="1df31b12" sha1="a1a3bb8bfeff3d0fde2724c6610c88f27f7056f9" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop13" interface="floppy_5_25">
+			<feature name="part_id" value="Learning Word 3" />
+			<dataarea name="flop" size = "368640">
+				<rom name="disk13 - Learning Word 3.img" size="368640" crc="6a4c88ed" sha1="84a03417c60d56c665abbd96847f23eef1933b44" offset="0"/>
+			</dataarea>
+		</part>
+	</software>
+
+	<!-- SDK -->
+
+	<software name="win13sdk">
+		<description>Windows 1.03 SDK</description>
+		<year>1986</year>
+		<publisher>Microsoft</publisher>
+
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="utilities disk 1 (050-150-078).img" size="368640" crc="f2675ca3" sha1="352eb818acaf30119309300399c2acc9433efb8d" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="utilities disk 2 (050-150-079).img" size="368640" crc="96264321" sha1="fd34ac2c00f5d44aedf9f9a11fc54439450cfd7f" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop3" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="libraries and include files disk (c) (050-150-080).img" size="368640" crc="34478d1b" sha1="334134cd115cbae61603776bf16e86066a3f0dc6" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop4" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="libraries, include files, and sample source disk (pascal) (050-150-081).img" size="368640" crc="f3004306" sha1="affaeff13576e4f451a21c1bf3b39a8f475039c0" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop5" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="symbol and debug libraries (050-150-082).img" size="368640" crc="2f58fe8d" sha1="7682ce2d95372735f1d20776e5024faa0db25369" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop6" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="sample source code disk 1 (050-150-083).img" size="368640" crc="27a18dcd" sha1="2fcd89cd8239ba5435b754c3ff1b653461143c8e" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop7" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="sample source code disk 2 (050-150-084).img" size="368640" crc="8e762502" sha1="540e0a40059a25f5c16a8545e65421a9d0febdf8" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<!-- Operating Systems -->
+
+	<software name="cpm8610">
+		<description>CP/M-86 for the IBM Personal Computer (Version 1.0)</description>
+		<year>1982</year>
+		<publisher>Digital Research</publisher>
+		<info name="version" value="1.0" />
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size="163840">
+				<rom name="cpm86.img" size="163840" crc="79c8ef92" sha1="f4074a4b2f5826faa893869b163461a8808d13ef" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="cpm8611">
+		<description>CP/M-86 for the IBM Personal Computer (Version 1.1)</description>
+		<year>1982</year>
+		<publisher>Digital Research</publisher>
+		<info name="version" value="1.1" />
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size="109434">
+				<rom name="cpm8611.td0" size="109434" crc="c1b7a3f9" sha1="28c3e3edc9698680a63e0fa9ce6d58d6829fdc68" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="ecpm8611">
+		<description>Eagle CP/M-86 (Version 1.1B)</description>
+		<year>1983</year>
+		<publisher>Digital Research</publisher>
+		<info name="version" value="1.1B" />
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size="327680">
+				<rom name="cpm86-disk1.dsk" size="327680" crc="585295a0" sha1="4d026fcc175c79ffff190dce3182815944c122f3" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_5_25">
+			<dataarea name="flop" size="327680">
+				<rom name="cpm86-disk2.dsk" size="327680" crc="c780f765" sha1="9a4eafd6f6b7d01d1a39f63d245e0653263de189" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="msdos211">
+		<description>AT&T Personal Computer 6300 DOS Release 2.0 (MS-DOS 2.11)</description>
+		<year>1984</year>
+		<publisher>AT&T</publisher>
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="disk01.img" size="368640" crc="71cb84ef" sha1="278d3f796e84b851b5b1abd09b610c6a663aef1a" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="disk02.img" size="368640" crc="08cd78c2" sha1="5d7364d31350854e45b5346c3670c9c19e8cb7ee" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="msdos32" supported="no">
+		<description>MS-DOS (Version 3.2)</description>
+		<year>1985</year>
+		<publisher>Microsoft</publisher>
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="disk1.img" size="368640" crc="136579c0" sha1="dc50472d5355b7c29fab0361c262ef83dde6a2ea" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="disk2.img" size="368640" crc="c5e7e32f" sha1="c03f03494271bbdfb8865efa79bf8f5b5061b233" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop3" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="disk3.img" size="368640" crc="9a7366fe" sha1="e56a8fb2732a258bd50465c596ff5e16b53afae3" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<!-- Fatal error: Device 5.25" double density floppy drive load failed: Unable to identify the image format -->
+	<software name="msdos33" supported="no">
+		<description>MS-DOS (Version 3.30)</description>
+		<year>1987</year>
+		<publisher>Microsoft</publisher>
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size="369152">
+				<rom name="disk1.img" size="369152" crc="812d0573" sha1="1fe01c291fbacc5d97c86ea8aef21289669bab9c" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_5_25">
+			<dataarea name="flop" size="369152">
+				<rom name="disk2.img" size="369152" crc="489b485b" sha1="cc97e6f33df9df2b7a459dbcf0bba86778667534" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="msdos33a">
+		<description>MS-DOS (Version 3.30A)</description>
+		<year>1987</year>
+		<publisher>Microsoft</publisher>
+		<info name="version" value="3.30A" />
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="disk1.img" size="368640" crc="b34d23a3" sha1="25488e58b6a462e7681940b589bd33c3ddcf2ae7" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="disk2.img" size="368640" crc="376ac8a2" sha1="ab165a11bc79d4cb6819e7901fea3cbcfa2de1a8" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="msdos33k" cloneof="msdos33">
+		<description>MS-DOS (Version 3.30) (Knowledge Dynamics Corp)</description>
+		<year>1993</year>
+		<publisher>Knowledge Dynamics Corp</publisher>
+		<part name="flop1" interface="floppy_5_25">
+			<feature name="disk_serial" value="02042 036214.330A" />
+			<feature name="disk_label" value="Programs" />
+			<dataarea name="flop" size="368640">
+				<rom name="disk 1.img" size="368640" crc="db07d99a" sha1="121ad3c636a69dae3a8eee96ef2ebf1152e9d00f" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_3_5">
+			<feature name="disk_serial" value="02043 036214.330A" />
+			<feature name="disk_label" value="Additional Programs and Microsoft GW-Basic Interpreter" />
+			<dataarea name="flop" size="368640">
+				<rom name="disk 2.img" size="368640" crc="bef8e643" sha1="97df57499e009101d04bd696d23024b4d220e297" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<!-- not original, from jsmachines -->
+	<software name="msdos4">
+		<description>MS-DOS (Version 4.00)</description>
+		<year>1985</year>
+		<publisher>Microsoft</publisher>
+		<info name="version" value="4.00" />
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="msdos400m-disk1.img" size="368640" crc="67848d5c" sha1="9e44fc3ed1f689c4136a08d48f9efa156cbaf250" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="msdos400m-disk2-unpatched.img" size="368640" crc="85a8cb6c" sha1="88d8ec84a6e24f2c918508dc65de0cdee182a48e" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="msdos401">
+		<description>MS-DOS (Version 4.01)</description>
+		<year>1988</year>
+		<publisher>Microsoft</publisher>
+		<info name="version" value="4.01" />
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="737280">
+				<rom name="setup.img" size="737280" crc="ff363533" sha1="6cbf2bcf051d168d542c289aeb630f98fc2a56a7" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_3_5">
+			<dataarea name="flop" size="737280">
+				<rom name="operating.img" size="737280" crc="f0e2b019" sha1="e4f0dc4df9df1581a2acb109b5159ca142005707" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop3" interface="floppy_3_5">
+			<dataarea name="flop" size="737280">
+				<rom name="dos shell.img" size="737280" crc="7be56e89" sha1="2f45b4a5140c04d572a8be6e3ef4011edb741b5b" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<!-- Fatal error: Device 5.25" double density floppy drive load failed: Unable to identify the image format -->
+	<software name="msdos401m" cloneof="msdos401" supported="no">
+		<description>MS-DOS (Version 4.01, 5.25")</description>
+		<year>1988</year>
+		<publisher>Microsoft</publisher>
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size="369152">
+				<rom name="install.img" size="369152" crc="ceeb1691" sha1="9d69d99a7c7a9b903e3f8c1e3f02b68270feff9c" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_5_25">
+			<dataarea name="flop" size="369152">
+				<rom name="operating 1.img" size="369152" crc="1b37564d" sha1="bce6027533ff4252229fe017f676de0cff653b3a" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop3" interface="floppy_5_25">
+			<dataarea name="flop" size="369152">
+				<rom name="operating 2.img" size="369152" crc="d33a9768" sha1="0dba1f9ce818dae3ced74e04dab9a07976a3d720" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop4" interface="floppy_5_25">
+			<dataarea name="flop" size="369152">
+				<rom name="operating 3.img" size="369152" crc="6776d4f9" sha1="6d2a569c2d1cd3237bc1964c14b10396dd9c461e" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop5" interface="floppy_5_25">
+			<dataarea name="flop" size="369152">
+				<rom name="select.img" size="369152" crc="7979de98" sha1="23fc5ce0ac5dee1a89fbe8ba6f96e5f1a5f7800b" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop6" interface="floppy_5_25">
+			<dataarea name="flop" size="369152">
+				<rom name="shell.img" size="369152" crc="c40b54a2" sha1="181b6668eb5f3f11f817ccc5d576389911254261" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="msdos5">
+		<description>MS-DOS (Version 5.00, 5.25")</description>
+		<year>1991</year>
+		<publisher>Microsoft</publisher>
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="disk01.img" size="368640" crc="54f94294" sha1="6a66bdcdc141eaa8dbcbea8d344b7012add15672" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="disk02.img" size="368640" crc="224bde66" sha1="7fcc9e283d5245c4eb3e2d0a5e4f7abd2cb2cc7b" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop3" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="disk03.img" size="368640" crc="ad5aff11" sha1="447d6e95ae2e19bc783c5ca3934cbe796e6023de" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop4" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="disk04.img" size="368640" crc="6853a453" sha1="fcf640843977bfd5c40fd059a3d2203aab337977" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop5" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="disk05.img" size="368640" crc="6592c217" sha1="35ed264ef14719a7bc6373d2e7d0688170d53442" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="msdos5a" cloneof="msdos5">
+		<description>MS-DOS (Version 5.00, 5.25", RTM)</description>
+		<year>1991</year>
+		<publisher>Microsoft</publisher>
+		<info name="OEM" value="Mecer" />
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="disk 1.img" size="368640" crc="de9e3bf6" sha1="b78aaced6bf262a5aa7af6d328caaf8370539c7c" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="disk 2.img" size="368640" crc="b56623db" sha1="0424273d8b63a1d89a880c6737278bcf6003e5d5" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop3" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="disk 3.img" size="368640" crc="273b0fb7" sha1="79595c7831ffa5599f3682e7a9bf43c7b7620387" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop4" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="disk 4.img" size="368640" crc="69e4c763" sha1="af69f1c0e897a5f19c52941bc6e4fdbe4d17db6e" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop5" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="disk 5.img" size="368640" crc="3de11d76" sha1="b808a9b294b660454ddd84c014525052e6f9223e" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="msdos5_35" cloneof="msdos5">
+		<description>MS-DOS (Version 5.00, 3.5")</description>
+		<year>1991</year>
+		<publisher>Microsoft</publisher>
+		<info name="version" value="5.00" />
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="737280">
+				<rom name="disk01_35.img" size="737280" crc="a34dc98f" sha1="791e291a16a7ce3b3ffb536b1c27dfe8e620338e" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_3_5">
+			<dataarea name="flop" size="737280">
+				<rom name="disk02_35.img" size="737280" crc="332cb5b4" sha1="0e1f4f63d68d02b5224a69e73ee9b7a3e630a1bb" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop3" interface="floppy_3_5">
+			<dataarea name="flop" size="737280">
+				<rom name="disk03_35.img" size="737280" crc="758c9037" sha1="53ba701accbf58db3b43188f4b4769a6a8008e05" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="msdos5u" cloneof="msdos5">
+		<description>MS-DOS (Version 5.00, 5.25", Upgrade)</description>
+		<year>1991</year>
+		<publisher>Microsoft</publisher>
+		<info name="version" value="5.00" />
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="disk01u.img" size="368640" crc="0dd44931" sha1="47b077300d22f2a86de31855ee8e1ff215aa592f" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="disk02u.img" size="368640" crc="b7fcb627" sha1="bd0655ed4999bc792a699f89588e4773ee33335b" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop3" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="disk03u.img" size="368640" crc="614b279e" sha1="c5e02fae37b5ed7a2f761a21973b14c2ce56294c" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop4" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="disk04u.img" size="368640" crc="90fc6384" sha1="73ea8e782238d786d108be9bcb40fcab7e11269a" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop5" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="disk05u.img" size="368640" crc="5b436ce1" sha1="b8b4b3c4b905a90ca13910d0230deeb7fe04273f" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop6" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="disk06u.img" size="368640" crc="fc26ce05" sha1="a4471bc3d43dec17b116f0b673ab10103ca14a25" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="msdos5ua" cloneof="msdos5">
+		<description>MS-DOS (Version 5.00, 5.25", Upgrade, RTM)</description>
+		<year>1991</year>
+		<publisher>Microsoft</publisher>
+		<info name="OEM" value="Mecer" />
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="disk 1 (upgrade).img" size="368640" crc="01a3d9a2" sha1="083400723e475ed497b276c9d4f2799eff3b88b8" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="disk 2 (upgrade).img" size="368640" crc="a8709827" sha1="9dbbbd267eb9b63447ee04641892ff0bea08cd25" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop3" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="disk 3 (upgrade).img" size="368640" crc="bb5bb90b" sha1="5fd3b4fe686d7459b7048ec8f1a38860755a887a" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop4" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="disk 4 (upgrade).img" size="368640" crc="b411a21d" sha1="7623d0fa4b178415c1b85e8d14e452c5fa0a5bf0" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop5" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="disk 5 (upgrade).img" size="368640" crc="26edd0f6" sha1="87b38570250dd12b6b4e4f232d6d3f3ab7960d6c" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop6" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="disk 6 (upgrade).img" size="368640" crc="782c0c4a" sha1="aaff65c8263ed44f7af69892a4b9c926ba0ccf75" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="msdos5m" cloneof="msdos5">
+		<description>MS-DOS (Version 5.00, Mecer OEM)</description>
+		<year>1991</year>
+		<publisher>Microsoft</publisher>
+		<info name="OEM" value="Mecer" />
+		<part name="flop1" interface="floppy_3_5">
+			<feature name="disk_serial" value="0044238" />
+			<dataarea name="flop" size="737280">
+				<rom name="operating 1.img" size="737280" crc="c54fe610" sha1="27756a10edbe33f76ff2239062af05dbfdc93979" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_3_5">
+			<feature name="disk_serial" value="0045925" />
+			<dataarea name="flop" size="737280">
+				<rom name="operating 2.img" size="737280" crc="9aa5c1a4" sha1="15cc58e267601b30a594372aea1ff3dbb73ea335" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop3" interface="floppy_3_5">
+			<feature name="disk_serial" value="0044171" />
+			<dataarea name="flop" size="737280">
+				<rom name="operating 3.img" size="737280" crc="6248317a" sha1="c7ff3a04eb01cab3efb05b6b52ec8b8a36b9b269" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="pcdos1">
+		<description>IBM Personal Computer DOS (Version 1.00)</description>
+		<year>1981</year>
+		<publisher>IBM</publisher>
+		<info name="version" value="1.00" />
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size="163840">
+				<rom name="pcdos100.img" size="163840" crc="2df1c1c8" sha1="7d3e3a807ad2144315b3c3b90751ff691d3895db" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="pcdos11">
+		<description>IBM Personal Computer DOS (Version 1.10)</description>
+		<year>1982</year>
+		<publisher>IBM</publisher>
+		<info name="version" value="1.10" />
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size="163840">
+				<rom name="ibmdos11.img" size="163840" crc="ddfe9550" sha1="437bec5be7d28cc2248d5477f38a07545816e49a" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="pcdos2">
+		<description>IBM Personal Computer DOS (Version 2.00)</description>
+		<year>1983</year>
+		<publisher>IBM</publisher>
+		<info name="version" value="2.00" />
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="ibmdos 2.img" size="368640" crc="d0fb7d31" sha1="cbee7f6109fb0ed8a94de1893fc47ab066de36d3" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="pcdos2a" cloneof="pcdos2">
+		<description>IBM Personal Computer DOS (Version 2.00, Alt)</description>
+		<year>1983</year>
+		<publisher>IBM</publisher>
+		<info name="version" value="2.00" />
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size="184320">
+				<rom name="ibmdos 2 (disk 1).img" size="184320" crc="b8f8ce15" sha1="e4478aeece1aa1627ac595e5fca96fbd8ad562c7" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_5_25">
+			<dataarea name="flop" size="184320">
+				<rom name="ibmdos 2 (disk 2).img" size="184320" crc="cf37729c" sha1="4f6fcc26d4382a8fed950bfaa8961669d513f93b" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="pcdos3">
+		<description>IBM Personal Computer DOS (Version 3.00)</description>
+		<year>1984</year>
+		<publisher>IBM</publisher>
+		<info name="version" value="3.00" />
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop1" size="368640">
+				<rom name="6322635.img" size="368640" crc="20a3dc1c" sha1="1e7430c57109960fd89d281d24e85a086a8284e4" offset="0" />
+			</dataarea>
+			<dataarea name="flop2" size="368640">
+				<rom name="6322640.img" size="368640" crc="eb75a4c0" sha1="bdb8528a71ea35cb1d9a0a0f13f8f0b745ca8eb6" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<!-- doesn't boot, bad dump? -->
+	<software name="pcdos3a" cloneof="pcdos3" supported="no">
+		<description>IBM Personal Computer DOS (Version 3.00, Alternate)</description>
+		<year>1984</year>
+		<publisher>IBM</publisher>
+		<info name="version" value="3.00" />
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="disk1.img" size="368640" crc="7a24e3bf" sha1="8cfebd5548b918c8d03f501ef02e66aca4ce3231" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="disk2.img" size="368640" crc="33184477" sha1="a7c150881903359859e46f9fe2de21d5c3afba99" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="pcdos31">
+		<description>IBM Personal Computer DOS (Version 3.10)</description>
+		<year>1985</year>
+		<publisher>IBM</publisher>
+		<info name="version" value="3.10" />
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="disk1.img" size="368640" crc="4b7ac87b" sha1="6f6ff69c4e2c14e2d64af06f1af9b60655d705a0" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="disk2.img" size="368640" crc="73eda674" sha1="1e6bb4a676137acbf6ff0cf59f94e206056c5821" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<!-- Fatal error: Device 5.25" double density floppy drive load failed: Unable to identify the image format -->
+	<software name="pcdos32" supported="no">
+		<description>IBM Personal Computer DOS (Version 3.20)</description>
+		<year>1986</year>
+		<publisher>IBM</publisher>
+		<info name="version" value="3.20" />
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size="405504">
+				<rom name="disk1.img" size="405504" crc="d4f4bfad" sha1="dab0710c79625a3e104b8945d7d179009376773a" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="pcdos33">
+		<description>IBM Personal Computer DOS (Version 3.30)</description>
+		<year>1987</year>
+		<publisher>IBM</publisher>
+		<info name="version" value="3.30" />
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="startup.img" size="368640" crc="402f4949" sha1="c6dc54ae6cbf810a0f54403c68acc1a10caedc21" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="operating.img" size="368640" crc="b0e167b0" sha1="4f582d07b1c4c18c6582ff8e53311a37c109aced" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="pcdos5">
+		<description>IBM DOS (Version 5.00)</description>
+		<year>1991</year>
+		<publisher>IBM</publisher>
+		<info name="version" value="5.00" />
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="737280">
+				<rom name="disk1.img" size="737280" crc="49ee0681" sha1="30fedf09e8b55eadc35c387968bcd02620630a27" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_3_5">
+			<dataarea name="flop" size="737280">
+				<rom name="disk2.img" size="737280" crc="9cfecb72" sha1="ffef155e6c746602e9ea28aef091119055f4cdb4" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop3" interface="floppy_3_5">
+			<dataarea name="flop" size="737280">
+				<rom name="disk3.img" size="737280" crc="8414bc1f" sha1="d6ebe11bba3d995f574e0385358edbdd52a6b219" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="pcdos502">
+		<description>IBM DOS (Version 5.02)</description>
+		<year>1992</year>
+		<publisher>IBM</publisher>
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size="737280">
+				<rom name="disk1.img" size="737280" crc="c3d4b69e" sha1="8e8fdbf1a39cbf541c5e8e3afa9351d3afef41bd" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_3_5">
+			<dataarea name="flop" size="737280">
+				<rom name="disk2.img" size="737280" crc="05c5345e" sha1="6d1fc805f9602836a379042d36edad56d692e922" offset="0" />
+			</dataarea>
+		</part>
+		<part name="flop3" interface="floppy_3_5">
+			<dataarea name="flop" size="737280">
+				<rom name="disk3.img" size="737280" crc="d63b96f5" sha1="ae0ed2b14cd5477b2239a40a9987b23db8a1e28c" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<!-- Dos based Games -->
+
+	<software name="2400ad" supported="no"> <!-- unemulated protection, game needs cracked exe to play ATM  -->
+		<description>2400 A.D.</description>
+		<year>1987</year>
+		<publisher>Origin</publisher>
+		<info name="version" value="1.0" />
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="2400ad.img" size="368640" crc="bf246734" sha1="a9f0be5fa2a5077375dae572622926bb8aa9e28a" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="688atsub">
+		<description>688 Attack Sub</description>
+		<year>1989</year>
+		<publisher>Electronic Arts</publisher>
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size = "737280">
+				<rom name="688 Attack Sub [1989] [Electronic Arts] [3.5] [1 of 1].img" size="737280" crc="a6ab2fdd" sha1="b36511db1302202ee1056bbabafe78cfdbfb7c29" offset="0"/>
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="academy" supported="no">
+		<description>Academy - Tau Ceti 2</description>
+		<year>1987</year>
+		<publisher>CRL Group</publisher>
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size = "368640">
+				<rom name="Academy - Tau Ceti 2 [1987] [CRL Group] [5.25] [1 of 1].img" size="368640" crc="d9047aa4" sha1="09198868eb826dc1be90b941f66c336d21f5df92" offset="0"/>
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="aceoface">
+		<description>Ace of Aces</description>
+		<year>1987</year>
+		<publisher>Accolade</publisher>
+		<info name="developer" value="Artech" />
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size = "737280">
+				<rom name="Ace of Aces [Accolade] [1987] [3.5].img" size="737280" crc="9f5d1734" sha1="db70bf0ede554db32c8bf3142b199e627f7ecebd" offset="0"/>
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="aaow">
+		<description>The Ancient Art of War</description>
+		<year>1984</year>
+		<publisher>Brøderbund Software</publisher>
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="the ancient art of war.img" size="368640" crc="32699e4b" sha1="f4a021d4bc5a9e61b7036cfcd41a43c2a146ab37" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="aaowas">
+		<description>The Ancient Art of War at Sea</description>
+		<year>1987</year>
+		<publisher>Brøderbund Software</publisher>
+		<info name="version" value="1.0" />
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="the ancient art of war at sea.img" size="368640" crc="e9c9f3af" sha1="379376f6255d24a71dc8d156e580966d067b3a84" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="aaowasa" cloneof="aaowas">
+		<description>The Ancient Art of War at Sea (Alt)</description>
+		<year>1987</year>
+		<publisher>Brøderbund Software</publisher>
+		<info name="version" value="1.5?" />
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size="368640">
+				<rom name="the ancient art of war at sea (alt).img" size="368640" crc="ac538af6" sha1="143b797aa13d71af042fa6f4b21679f25338c633" offset="0" />
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="bargames">
+		<description>Bar Games</description>
+		<year>1989</year>
+		<publisher>Accolade</publisher>
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size = "368640">
+				<rom name="Bar Games [Accolade] [1989] [5.25] [1].img" size="368640" crc="deb3e64c" sha1="727ae13bd59b19feee0269e08dc831e1393c4a71" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_5_25">
+			<dataarea name="flop" size = "368640">
+				<rom name="Bar Games [Accolade] [1989] [5.25] [2].img" size="368640" crc="684dbc8b" sha1="667d77f7a441e461160545dfb16602898c2e1b2d" offset="0"/>
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="brdtale">
+		<description>The Bard's Tale - Tales of the Unknown (5.25")</description>
+		<year>1987</year>
+		<publisher>Electronic Arts</publisher>
+		<info name="developer" value="Interplay Productions" />
+		<part name="flop1" interface="floppy_5_25">
+			<feature name="part_id" value="Program Disk" />
+			<dataarea name="flop" size = "368640">
+				<rom name="The Bard's Tale 1 - Tales of the Unknown [1987] [5.25] [1 of 2].img" size="368640" crc="40918452" sha1="8cb08b1a090bb7e2b4021a28db27b8f2f9c9df71" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_5_25">
+			<feature name="part_id" value="Picture Disk" />
+			<dataarea name="flop" size = "368640">
+				<rom name="The Bard's Tale 1 - Tales of the Unknown [1987] [5.25] [2 of 2].img" size="368640" crc="a90bd7ec" sha1="68c4d04fb2625766018dcb4a34e27d8348fb817d" offset="0"/>
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="brdtalea" cloneof="brdtale">
+		<description>The Bard's Tale - Tales of the Unknown (5.25", alt)</description>
+		<year>1987</year>
+		<publisher>Electronic Arts</publisher>
+		<info name="developer" value="Interplay Productions" />
+		<part name="flop1" interface="floppy_5_25">
+			<feature name="part_id" value="Program Disk" />
+			<dataarea name="flop" size = "368640">
+				<rom name="The Bard's Tale 1 - Tales of the Unknown [1987] [5.25] [1 of 2].img" size="368640" crc="40918452" sha1="8cb08b1a090bb7e2b4021a28db27b8f2f9c9df71" offset="0"/>
 			</dataarea>
 		</part>
 		<part name="flop2" interface="floppy_5_25">
@@ -3062,6 +3909,99 @@ Known PC Booter Games Not Dumped, Or Dumped and Lost when Demonlord's Site went
 		</part>
 	</software>
 
+	<software name="caveugh">
+		<description>Caveman Ugh-Lympics</description>
+		<year>1988</year>
+		<publisher>Electronic Arts, Inc.</publisher>
+		<info name="developer" value="Dynamix, Inc." />
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size = "368640">
+				<rom name="Caveman Ugh-Lympics [1988] [5.25] [1 of 4].img" size="368640" crc="e2b6a566" sha1="92be8b5883718a2df46eee48f30b8db1088ab39c" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_5_25">
+			<dataarea name="flop" size = "368640">
+				<rom name="Caveman Ugh-Lympics [1988] [5.25] [2 of 4].img" size="368640" crc="d83db289" sha1="fb7e5838b8fbbc504e79093c57b4fb9533dc0baf" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop3" interface="floppy_5_25">
+			<dataarea name="flop" size = "368640">
+				<rom name="Caveman Ugh-Lympics [1988] [5.25] [3 of 4].img" size="368640" crc="e5164e7f" sha1="b42ddf8089fa2a2eb1f0a2a7103a54a7c528a790" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop4" interface="floppy_5_25">
+			<dataarea name="flop" size = "368640">
+				<rom name="Caveman Ugh-Lympics [1988] [5.25] [4 of 4].img" size="368640" crc="0091cb19" sha1="aeaf3725bbdf49a4ace38c7430183492a5da4384" offset="0"/>
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="dmnstomb">
+		<description>Demon's Tomb - The Awakening</description>
+		<year>1989</year>
+		<publisher>Virgin Mastertronic</publisher>
+		<info name="developer" value="Silhouette Software" />
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size = "368640">
+				<rom name="Demon's Tomb - The Awakening [1989] [Virgin Mastertronic] [5.25] [1 of 2].img" size="368640" crc="c63d8ff1" sha1="8282a157ec5a5c6020d5e5a9912dd2fd06212a85" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_5_25">
+			<dataarea name="flop" size = "368640">
+				<rom name="Demon's Tomb - The Awakening [1989] [Virgin Mastertronic] [5.25] [2 of 2].img" size="368640" crc="5bce4b3f" sha1="c4b3c19fc60e4cf99bbf1a0ec2f52830f55d1536" offset="0"/>
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="goldrush">
+		<description>Gold Rush (Version 2.01, 5.25")</description>
+		<year>1988</year>
+		<publisher>Sierra</publisher>
+		<info name="version" value="2.01" />
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size = "368640">
+				<rom name="Gold Rush [1988] [Sierra On-Line] [5.25] [1 of 5].img" size="368640" crc="1120e384" sha1="8b80213593f8d76f7903380e5003904a0232beea" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_5_25">
+			<dataarea name="flop" size = "368640">
+				<rom name="Gold Rush [1988] [Sierra On-Line] [5.25] [2 of 5].img" size="368640" crc="ae812659" sha1="af0a62d6ab8882bf1c517756394395c8304653f3" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop3" interface="floppy_5_25">
+			<dataarea name="flop" size = "368640">
+				<rom name="Gold Rush [1988] [Sierra On-Line] [5.25] [3 of 5].img" size="368640" crc="6c6d7d41" sha1="e379988de70cf4d6be9d151b70927ff21e560189" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop4" interface="floppy_5_25">
+			<dataarea name="flop" size = "368640">
+				<rom name="Gold Rush [1988] [Sierra On-Line] [5.25] [4 of 5].img" size="368640" crc="eb1ca8f0" sha1="d6b916f003e01af904c57ddd9ee0f76cd00200b7" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop5" interface="floppy_5_25">
+			<dataarea name="flop" size = "368640">
+				<rom name="Gold Rush [1988] [Sierra On-Line] [5.25] [5 of 5].img" size="368640" crc="ad940acf" sha1="592edc5c1da10fcfb689bc89660cf120a7e15102" offset="0"/>
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="goldrush35" cloneof="goldrush">
+		<description>Gold Rush (Version 2.01, 3.5")</description>
+		<year>1988</year>
+		<publisher>Sierra</publisher>
+		<info name="version" value="2.01" />
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size = "737280">
+				<rom name="Gold Rush [1988] [Sierra On-Line] [3.5] [1 of 2].img" size="737280" crc="5d6de39c" sha1="3b230cc9456ff93cd08123606a2e05630ff73556" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_3_5">
+			<dataarea name="flop" size = "737280">
+				<rom name="Gold Rush [1988] [Sierra On-Line] [3.5] [2 of 2].img" size="737280" crc="db6bcf7e" sha1="bafeaca31872785f4b7b22496beac2dc12816c72" offset="0"/>
+			</dataarea>
+		</part>
+	</software>
+
 	<software name="armorik">
 		<description>Les 8 Conquêtes d'Armorik le Viking</description>
 		<year>1988</year>
@@ -3400,4 +4340,29 @@ Known PC Booter Games Not Dumped, Or Dumped and Lost when Demonlord's Site went
 			</dataarea>
 		</part>
 	</software>
+
+	<!-- Demoscene -->
+
+	<software name="8088mph" supported="partial">
+		<description>8088 MPH (Final Version)</description>
+		<year>2015</year>
+		<publisher>Hornet + CRTC + DESiRE</publisher>
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size = "368640">
+				<rom name="8088mph final.360" size="368640" crc="a30504e8" sha1="5f637b83dca774b7104fed0d20195dd769e0838b" offset="0"/>
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="8088mphp" cloneof="8088mph" supported="partial">
+		<description>8088 MPH (Revision 2015 Party version)</description>
+		<year>2015</year>
+		<publisher>Hornet + CRTC + DESiRE</publisher>
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size = "368640">
+				<rom name="8088mph.360" size="368640" crc="4f5f4871" sha1="b7f61ad133edf7e80d2ccd0bc7767baf0b13f34d" offset="0"/>
+			</dataarea>
+		</part>
+	</software>
+
 </softwarelist>
diff --git a/hash/ibm5160_flop.xml b/hash/ibm5160_flop.xml
deleted file mode 100644
index 9ed0767..0000000
--- a/hash/ibm5160_flop.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE softwarelist SYSTEM "softwarelist.dtd">
-<softwarelist name="ibm5160_flop" description="IBM PC/XT disk images">
-
-	<!-- Operating Systems -->
-	<software name="pcdos20">
-		<description>PC DOS 2.0</description>
-		<year>1983</year>
-		<publisher>IBM</publisher>
-		<part name="flop1" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="disk1.img" size="368640" crc="d0fb7d31" sha1="cbee7f6109fb0ed8a94de1893fc47ab066de36d3" offset="0" />
-			</dataarea>
-		</part>
-	</software>
-
-</softwarelist>
diff --git a/hash/ibm5170.xml b/hash/ibm5170.xml
index c7a0008..927fa5b 100644
--- a/hash/ibm5170.xml
+++ b/hash/ibm5170.xml
@@ -1153,69 +1153,11 @@ Missing files come here
 		</part>
 	</software>
 
-	<software name="pcdos30">
-		<description>PC DOS 3.0</description>
-		<year>1984</year>
-		<publisher>IBM</publisher>
-		<part name="flop1" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="disk1.img" size="368640" crc="7a24e3bf" sha1="8cfebd5548b918c8d03f501ef02e66aca4ce3231" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop2" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="disk2.img" size="368640" crc="33184477" sha1="a7c150881903359859e46f9fe2de21d5c3afba99" offset="0" />
-			</dataarea>
-		</part>
-	</software>
-
-	<software name="pcdos31">
-		<description>PC DOS 3.1</description>
-		<year>1985</year>
-		<publisher>IBM</publisher>
-		<part name="flop1" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="disk1.img" size="368640" crc="4b7ac87b" sha1="6f6ff69c4e2c14e2d64af06f1af9b60655d705a0" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop2" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="disk2.img" size="368640" crc="73eda674" sha1="1e6bb4a676137acbf6ff0cf59f94e206056c5821" offset="0" />
-			</dataarea>
-		</part>
-	</software>
-
-	<software name="pcdos32">
-		<description>PC DOS 3.2</description>
-		<year>1986</year>
-		<publisher>IBM</publisher>
-		<part name="flop1" interface="floppy_5_25">
-			<dataarea name="flop" size="405504">
-				<rom name="disk1.img" size="405504" crc="d4f4bfad" sha1="dab0710c79625a3e104b8945d7d179009376773a" offset="0" />
-			</dataarea>
-		</part>
-	</software>
-
-	<software name="pcdos330">
-		<description>PC DOS 3.30</description>
-		<year>1987</year>
-		<publisher>IBM</publisher>
-		<part name="flop1" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="startup.img" size="368640" crc="402f4949" sha1="c6dc54ae6cbf810a0f54403c68acc1a10caedc21" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop2" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="operating.img" size="368640" crc="b0e167b0" sha1="4f582d07b1c4c18c6582ff8e53311a37c109aced" offset="0" />
-			</dataarea>
-		</part>
-	</software>
-
-	<software name="pcdos400">
-		<description>PC DOS 4.00</description>
+	<software name="pcdos4">
+		<description>IBM Personal Computer DOS (Version 4.00)</description>
 		<year>1988</year>
 		<publisher>IBM</publisher>
+		<info name="version" value="4.00" />
 		<part name="flop1" interface="floppy_3_5">
 			<dataarea name="flop" size="737280">
 				<rom name="install.img" size="737280" crc="edcb2ea3" sha1="352dffca01bd72349503024d0b9d16c4b684f791" offset="0" />
@@ -1228,52 +1170,11 @@ Missing files come here
 		</part>
 	</software>
 
-	<software name="pcdos500">
-		<description>PC DOS 5.00</description>
-		<year>1991</year>
-		<publisher>IBM</publisher>
-		<part name="flop1" interface="floppy_3_5">
-			<dataarea name="flop" size="737280">
-				<rom name="disk1.img" size="737280" crc="49ee0681" sha1="30fedf09e8b55eadc35c387968bcd02620630a27" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop2" interface="floppy_3_5">
-			<dataarea name="flop" size="737280">
-				<rom name="disk2.img" size="737280" crc="9cfecb72" sha1="ffef155e6c746602e9ea28aef091119055f4cdb4" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop3" interface="floppy_3_5">
-			<dataarea name="flop" size="737280">
-				<rom name="disk3.img" size="737280" crc="8414bc1f" sha1="d6ebe11bba3d995f574e0385358edbdd52a6b219" offset="0" />
-			</dataarea>
-		</part>
-	</software>
-
-	<software name="pcdos502">
-		<description>PC DOS 5.02</description>
-		<year>1992</year>
-		<publisher>IBM</publisher>
-		<part name="flop1" interface="floppy_3_5">
-			<dataarea name="flop" size="737280">
-				<rom name="disk1.img" size="737280" crc="c3d4b69e" sha1="8e8fdbf1a39cbf541c5e8e3afa9351d3afef41bd" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop2" interface="floppy_3_5">
-			<dataarea name="flop" size="737280">
-				<rom name="disk2.img" size="737280" crc="05c5345e" sha1="6d1fc805f9602836a379042d36edad56d692e922" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop3" interface="floppy_3_5">
-			<dataarea name="flop" size="737280">
-				<rom name="disk3.img" size="737280" crc="d63b96f5" sha1="ae0ed2b14cd5477b2239a40a9987b23db8a1e28c" offset="0" />
-			</dataarea>
-		</part>
-	</software>
-
 	<software name="pcdos61">
-		<description>PC DOS 6.1</description>
+		<description>IBM DOS (Version 6.1)</description>
 		<year>1993</year>
 		<publisher>IBM</publisher>
+		<info name="version" value="6.1" />
 		<part name="flop1" interface="floppy_3_5">
 			<feature name="part_id" value="Diskette 1 of 4"/>
 			<dataarea name="flop" size="1474560">
@@ -1300,10 +1201,11 @@ Missing files come here
 		</part>
 	</software>
 
-	<software name="pcdos630">
-		<description>PC DOS 6.30</description>
+	<software name="pcdos63">
+		<description>PC DOS (Version 6.3)</description>
 		<year>1993</year>
 		<publisher>IBM</publisher>
+		<info name="version" value="6.3" />
 		<part name="flop1" interface="floppy_3_5">
 			<dataarea name="flop" size="1474560">
 				<rom name="disk1.img" size="1474560" crc="0fc87254" sha1="2b4166557ea8eba7d6b0f3a4d9376896bf5a217c" offset="0" />
@@ -1331,7 +1233,7 @@ Missing files come here
 		</part>
 	</software>
 
-	<software name="pcdos70">
+	<software name="pcdos7" supported="no">
 		<description>PC DOS 7.0</description>
 		<year>1995</year>
 		<publisher>IBM</publisher>
@@ -1367,79 +1269,11 @@ Missing files come here
 		</part>
 	</software>
 
-	<software name="msdos211">
-		<description>MS-DOS 2.11</description>
-		<year>1983</year>
-		<publisher>Microsoft</publisher>
-		<part name="flop1" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="disk01.img" size="368640" crc="71cb84ef" sha1="278d3f796e84b851b5b1abd09b610c6a663aef1a" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop2" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="disk02.img" size="368640" crc="08cd78c2" sha1="5d7364d31350854e45b5346c3670c9c19e8cb7ee" offset="0" />
-			</dataarea>
-		</part>
-	</software>
-
-	<software name="msdos32">
-		<description>MS-DOS 3.2</description>
-		<year>1985</year>
-		<publisher>Microsoft</publisher>
-		<part name="flop1" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="disk1.img" size="368640" crc="136579c0" sha1="dc50472d5355b7c29fab0361c262ef83dde6a2ea" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop2" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="disk2.img" size="368640" crc="c5e7e32f" sha1="c03f03494271bbdfb8865efa79bf8f5b5061b233" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop3" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="disk3.img" size="368640" crc="9a7366fe" sha1="e56a8fb2732a258bd50465c596ff5e16b53afae3" offset="0" />
-			</dataarea>
-		</part>
-	</software>
-
-	<software name="msdos330">
-		<description>MS-DOS 3.30</description>
-		<year>1987</year>
-		<publisher>Microsoft</publisher>
-		<part name="flop1" interface="floppy_5_25">
-			<dataarea name="flop" size="369152">
-				<rom name="disk1.img" size="369152" crc="812d0573" sha1="1fe01c291fbacc5d97c86ea8aef21289669bab9c" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop2" interface="floppy_5_25">
-			<dataarea name="flop" size="369152">
-				<rom name="disk2.img" size="369152" crc="489b485b" sha1="cc97e6f33df9df2b7a459dbcf0bba86778667534" offset="0" />
-			</dataarea>
-		</part>
-	</software>
-
-	<software name="msdos33a">
-		<description>MS-DOS 3.30a</description>
-		<year>19??</year>
-		<publisher>Microsoft</publisher>
-		<part name="flop1" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="disk1.img" size="368640" crc="b34d23a3" sha1="25488e58b6a462e7681940b589bd33c3ddcf2ae7" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop2" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="disk2.img" size="368640" crc="376ac8a2" sha1="ab165a11bc79d4cb6819e7901fea3cbcfa2de1a8" offset="0" />
-			</dataarea>
-		</part>
-	</software>
-
 	<software name="msdos331">
-		<description>MS-DOS 3.31</description>
-		<year>19??</year>
+		<description>MS-DOS (Version 3.31, 3.5" HD)</description>
+		<year>1987</year>
 		<publisher>Microsoft</publisher>
+		<info name="version" value="3.31" />
 		<part name="flop1" interface="floppy_3_5">
 			<dataarea name="flop" size="1474560">
 				<rom name="disk1.img" size="1474560" crc="a864516e" sha1="35a275626d7973b856aeb163ee216157078b175a" offset="0" />
@@ -1447,192 +1281,54 @@ Missing files come here
 		</part>
 	</software>
 
-	<software name="msdos4m">
-		<description>MS-DOS 4.0M</description>
-		<year>1985</year>
-		<publisher>Microsoft</publisher>
-		<part name="flop1" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="msdos400m-disk1.img" size="368640" crc="67848d5c" sha1="9e44fc3ed1f689c4136a08d48f9efa156cbaf250" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop2" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="msdos400m-disk2-unpatched.img" size="368640" crc="85a8cb6c" sha1="88d8ec84a6e24f2c918508dc65de0cdee182a48e" offset="0" />
-			</dataarea>
-		</part>
-	</software>
-
-	<software name="msdos401">
-		<description>MS-DOS 4.01</description>
-		<year>1988</year>
-		<publisher>Microsoft</publisher>
-		<part name="flop1" interface="floppy_3_5">
-			<dataarea name="flop" size="737280">
-				<rom name="setup.img" size="737280" crc="ff363533" sha1="6cbf2bcf051d168d542c289aeb630f98fc2a56a7" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop2" interface="floppy_3_5">
-			<dataarea name="flop" size="737280">
-				<rom name="operating.img" size="737280" crc="f0e2b019" sha1="e4f0dc4df9df1581a2acb109b5159ca142005707" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop3" interface="floppy_3_5">
-			<dataarea name="flop" size="737280">
-				<rom name="dos shell.img" size="737280" crc="7be56e89" sha1="2f45b4a5140c04d572a8be6e3ef4011edb741b5b" offset="0" />
-			</dataarea>
-		</part>
-	</software>
-
-	<software name="msds401m">
-		<description>MS-DOS 4.01 (5.25")</description>
-		<year>1988</year>
-		<publisher>Microsoft</publisher>
-		<part name="flop1" interface="floppy_5_25">
-			<dataarea name="flop" size="369152">
-				<rom name="install.img" size="369152" crc="ceeb1691" sha1="9d69d99a7c7a9b903e3f8c1e3f02b68270feff9c" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop2" interface="floppy_5_25">
-			<dataarea name="flop" size="369152">
-				<rom name="operating 1.img" size="369152" crc="1b37564d" sha1="bce6027533ff4252229fe017f676de0cff653b3a" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop3" interface="floppy_5_25">
-			<dataarea name="flop" size="369152">
-				<rom name="operating 2.img" size="369152" crc="d33a9768" sha1="0dba1f9ce818dae3ced74e04dab9a07976a3d720" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop4" interface="floppy_5_25">
-			<dataarea name="flop" size="369152">
-				<rom name="operating 3.img" size="369152" crc="6776d4f9" sha1="6d2a569c2d1cd3237bc1964c14b10396dd9c461e" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop5" interface="floppy_5_25">
-			<dataarea name="flop" size="369152">
-				<rom name="select.img" size="369152" crc="7979de98" sha1="23fc5ce0ac5dee1a89fbe8ba6f96e5f1a5f7800b" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop6" interface="floppy_5_25">
-			<dataarea name="flop" size="369152">
-				<rom name="shell.img" size="369152" crc="c40b54a2" sha1="181b6668eb5f3f11f817ccc5d576389911254261" offset="0" />
-			</dataarea>
-		</part>
-	</software>
-
-	<software name="msdos50">
-		<description>MS-DOS 5.0</description>
-		<year>1991</year>
+	<software name="msdos6">
+		<description>MS-DOS (Version 6.00)</description>
+		<year>1992</year>
 		<publisher>Microsoft</publisher>
+		<info name="version" value="6.00" />
 		<part name="flop1" interface="floppy_3_5">
-			<dataarea name="flop" size="737280">
-				<rom name="disk01.img" size="737280" crc="a34dc98f" sha1="791e291a16a7ce3b3ffb536b1c27dfe8e620338e" offset="0" />
+			<dataarea name="flop" size="1474560">
+				<rom name="disk1.img" size="1474560" crc="662b4a3d" sha1="114d4075729fc338839637f8f57f184ea59a769e" offset="0" />
 			</dataarea>
 		</part>
 		<part name="flop2" interface="floppy_3_5">
-			<dataarea name="flop" size="737280">
-				<rom name="disk02.img" size="737280" crc="332cb5b4" sha1="0e1f4f63d68d02b5224a69e73ee9b7a3e630a1bb" offset="0" />
+			<dataarea name="flop" size="1474560">
+				<rom name="disk2.img" size="1474560" crc="24b611f7" sha1="4fc338c763890fa17a456427d42d06beca667d41" offset="0" />
 			</dataarea>
 		</part>
 		<part name="flop3" interface="floppy_3_5">
-			<dataarea name="flop" size="737280">
-				<rom name="disk03.img" size="737280" crc="758c9037" sha1="53ba701accbf58db3b43188f4b4769a6a8008e05" offset="0" />
-			</dataarea>
-		</part>
-	</software>
-
-	<software name="msdos50m">
-		<description>MS-DOS 5.0 (5.25")</description>
-		<year>1991</year>
-		<publisher>Microsoft</publisher>
-		<part name="flop1" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="disk01.img" size="368640" crc="54f94294" sha1="6a66bdcdc141eaa8dbcbea8d344b7012add15672" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop2" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="disk02.img" size="368640" crc="224bde66" sha1="7fcc9e283d5245c4eb3e2d0a5e4f7abd2cb2cc7b" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop3" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="disk03.img" size="368640" crc="ad5aff11" sha1="447d6e95ae2e19bc783c5ca3934cbe796e6023de" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop4" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="disk04.img" size="368640" crc="6853a453" sha1="fcf640843977bfd5c40fd059a3d2203aab337977" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop5" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="disk05.img" size="368640" crc="6592c217" sha1="35ed264ef14719a7bc6373d2e7d0688170d53442" offset="0" />
-			</dataarea>
-		</part>
-	</software>
-
-	<software name="msdos50u">
-		<description>MS-DOS 5.0 (Upgrade)</description>
-		<year>1991</year>
-		<publisher>Microsoft</publisher>
-		<part name="flop1" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="disk01.img" size="368640" crc="0dd44931" sha1="47b077300d22f2a86de31855ee8e1ff215aa592f" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop2" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="disk02.img" size="368640" crc="b7fcb627" sha1="bd0655ed4999bc792a699f89588e4773ee33335b" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop3" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="disk03.img" size="368640" crc="614b279e" sha1="c5e02fae37b5ed7a2f761a21973b14c2ce56294c" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop4" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="disk04.img" size="368640" crc="90fc6384" sha1="73ea8e782238d786d108be9bcb40fcab7e11269a" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop5" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="disk05.img" size="368640" crc="5b436ce1" sha1="b8b4b3c4b905a90ca13910d0230deeb7fe04273f" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop6" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="disk06.img" size="368640" crc="fc26ce05" sha1="a4471bc3d43dec17b116f0b673ab10103ca14a25" offset="0" />
+			<dataarea name="flop" size="1474560">
+				<rom name="disk3.img" size="1474560" crc="97cc651d" sha1="efd6c30929b30eebca052c55ac613ecab11b82d9" offset="0" />
 			</dataarea>
 		</part>
 	</software>
 
-	<software name="msdos60">
-		<description>MS-DOS 6.0</description>
+	<software name="msdos6u" cloneof="msdos6">
+		<description>MS-DOS (Version 6.00, Upgrade)</description>
 		<year>1992</year>
 		<publisher>Microsoft</publisher>
 		<part name="flop1" interface="floppy_3_5">
-			<dataarea name="flop" size="1474560">
-				<rom name="disk1.img" size="1474560" crc="662b4a3d" sha1="114d4075729fc338839637f8f57f184ea59a769e" offset="0" />
+			<dataarea name="flop" size = "1474560">
+				<rom name="disk1u.img" size="1474560" crc="1b8997a9" sha1="ef275b681314d99e4dccda51b75a60bd1b3f5de2" offset="0"/>
 			</dataarea>
 		</part>
 		<part name="flop2" interface="floppy_3_5">
-			<dataarea name="flop" size="1474560">
-				<rom name="disk2.img" size="1474560" crc="24b611f7" sha1="4fc338c763890fa17a456427d42d06beca667d41" offset="0" />
+			<dataarea name="flop" size = "1474560">
+				<rom name="disk2u.img" size="1474560" crc="879aa93e" sha1="89d9365b0cbfd3490178c22ad0088aed410716b9" offset="0"/>
 			</dataarea>
 		</part>
 		<part name="flop3" interface="floppy_3_5">
-			<dataarea name="flop" size="1474560">
-				<rom name="disk3.img" size="1474560" crc="97cc651d" sha1="efd6c30929b30eebca052c55ac613ecab11b82d9" offset="0" />
+			<dataarea name="flop" size = "1474560">
+				<rom name="disk3u.img" size="1474560" crc="edb823d0" sha1="127d28b3d016b771c190f875876c6f1ab67fb4cf" offset="0"/>
 			</dataarea>
 		</part>
 	</software>
 
-	<software name="msdos620">
-		<description>MS-DOS 6.20</description>
+	<software name="msdos62">
+		<description>MS-DOS (Version 6.20)</description>
 		<year>1993</year>
 		<publisher>Microsoft</publisher>
+		<info name="version" value="6.20" />
 		<part name="flop1" interface="floppy_3_5">
 			<dataarea name="flop" size="1474560">
 				<rom name="disk1.img" size="1474560" crc="23a8a1f2" sha1="cb4f53c46e39b60fa11543f356bc04080c2b7b8c" offset="0" />
@@ -1650,36 +1346,40 @@ Missing files come here
 		</part>
 	</software>
 
-	<software name="msds620u">
-		<description>MS-DOS 6.20 (Upgrade)</description>
+	<!-- not original, has WinImage header -->
+	<software name="msdos62u" cloneof="msdos62">
+		<description>MS-DOS (Version 6.20, Upgrade)</description>
 		<year>1993</year>
 		<publisher>Microsoft</publisher>
+		<info name="version" value="6.20" />
 		<part name="flop1" interface="floppy_3_5">
 			<dataarea name="flop" size="1474560">
-				<rom name="disk1.img" size="1474560" crc="e2852c46" sha1="10048dd8d24b2e65cb4dca7568d544b9ee99a084" offset="0" />
+				<rom name="disk1u.img" size="1474560" crc="e2852c46" sha1="10048dd8d24b2e65cb4dca7568d544b9ee99a084" offset="0" status="baddump" />
 			</dataarea>
 		</part>
 		<part name="flop2" interface="floppy_3_5">
 			<dataarea name="flop" size="1474560">
-				<rom name="disk2.img" size="1474560" crc="f083b635" sha1="165644b7c1ed791e2e993f27fd89dbf2af77eb30" offset="0" />
+				<rom name="disk2u.img" size="1474560" crc="f083b635" sha1="165644b7c1ed791e2e993f27fd89dbf2af77eb30" offset="0" status="baddump" />
 			</dataarea>
 		</part>
 		<part name="flop3" interface="floppy_3_5">
 			<dataarea name="flop" size="1474560">
-				<rom name="disk3.img" size="1474560" crc="0b62c415" sha1="b972d42b998b846b2802f848774a1408ae173f10" offset="0" />
+				<rom name="disk3u.img" size="1474560" crc="0b62c415" sha1="b972d42b998b846b2802f848774a1408ae173f10" offset="0" status="baddump" />
 			</dataarea>
 		</part>
 		<part name="flop4" interface="floppy_3_5">
+			<feature name="part_id" value="Supplemental" />
 			<dataarea name="flop" size="1474560">
-				<rom name="supplemental.img" size="1474560" crc="23e03482" sha1="3fac12de77cafdea28a68793b597410a594506f8" offset="0" />
+				<rom name="supplemental.img" size="1474560" crc="23e03482" sha1="3fac12de77cafdea28a68793b597410a594506f8" offset="0" status="baddump" />
 			</dataarea>
 		</part>
 	</software>
 
 	<software name="msdos621">
-		<description>MS-DOS 6.21</description>
+		<description>MS-DOS (Version 6.21)</description>
 		<year>1994</year>
 		<publisher>Microsoft</publisher>
+		<info name="version" value="6.21" />
 		<part name="flop1" interface="floppy_5_25">
 			<dataarea name="flop" size="1228800">
 				<rom name="disk1.img" size="1228800" crc="f600eec8" sha1="7ce713f473beb93d85059933d3b44044daedd834" offset="0" />
@@ -1708,9 +1408,10 @@ Missing files come here
 	</software>
 
 	<software name="msdos622">
-		<description>MS-DOS 6.22</description>
+		<description>MS-DOS (Version 6.22)</description>
 		<year>1994</year>
 		<publisher>Microsoft</publisher>
+		<info name="version" value="6.22" />
 		<part name="flop1" interface="floppy_3_5">
 			<dataarea name="flop" size="1474560">
 				<rom name="disk1.img" size="1474560" crc="adbd36fe" sha1="3fb0df208670ea5fafae451661017391a381bc9d" offset="0" />
@@ -1733,171 +1434,61 @@ Missing files come here
 		</part>
 	</software>
 
-	<software name="msds622u">
-		<description>MS-DOS 6.22 (Upgrade)</description>
+	<software name="msdos622a" cloneof="msdos622">
+		<!-- from Acer CPR 1.2 recovery CD-ROM -->
+		<description>MS-DOS (Version 6.22, Alt)</description>
 		<year>1994</year>
 		<publisher>Microsoft</publisher>
-		<part name="flop1" interface="floppy_3_5">
+		<info name="version" value="6.22" />
+		<part name="disk1" interface="floppy_3_5">
 			<dataarea name="flop" size="1474560">
-				<rom name="disk1.img" size="1474560" crc="4b7d4093" sha1="3f18e0f833ab3c0a6e231f0dffd2cfd849b40c26" offset="0" />
+				<rom name="disk1a.img" size="1474560" crc="69d8cfdd" sha1="30b4b2e99b26b0e5e7dbe61b9892e45fe751a3e8" offset="0" />
 			</dataarea>
 		</part>
-		<part name="flop2" interface="floppy_3_5">
+		<part name="disk2" interface="floppy_3_5">
 			<dataarea name="flop" size="1474560">
-				<rom name="disk2.img" size="1474560" crc="8bd7688d" sha1="dfb44325e69e58393adfe8c911f709c63db0399c" offset="0" />
+				<rom name="disk2a.img" size="1474560" crc="76258952" sha1="1f268c5487f31982848461b9d628ef10b552c849" offset="0" />
 			</dataarea>
 		</part>
-		<part name="flop3" interface="floppy_3_5">
+		<part name="disk3" interface="floppy_3_5">
 			<dataarea name="flop" size="1474560">
-				<rom name="disk3.img" size="1474560" crc="930f809d" sha1="cffa2e29b24d033218f73d1a4ba0b19f0a179316" offset="0" />
-			</dataarea>
-		</part>
-	</software>
-
-	<software name="msd622mu">
-		<description>MS-DOS 6.22 (5.25" Upgrade)</description>
-		<year>1994</year>
-		<publisher>Microsoft</publisher>
-		<part name="flop1" interface="floppy_5_25">
-			<dataarea name="flop" size="1228800">
-				<rom name="disk1.img" size="1228800" crc="9519c473" sha1="1a2ca99b7ae94f21555326695cbb14a9a1898eee" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop2" interface="floppy_5_25">
-			<dataarea name="flop" size="1228800">
-				<rom name="disk2.img" size="1228800" crc="f70f29ab" sha1="f0a37131ba662ca3b8d0d0a291279497b533c156" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop3" interface="floppy_5_25">
-			<dataarea name="flop" size="1228800">
-				<rom name="disk3.img" size="1228800" crc="8980019f" sha1="ed14124c32e5075bad74729b2237bf9ef3e53e24" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop4" interface="floppy_5_25">
-			<dataarea name="flop" size="1228800">
-				<rom name="disk4.img" size="1228800" crc="4d7453ab" sha1="f7063a4f9e129ac25013b6b3223e028d758f71aa" offset="0" />
-			</dataarea>
-		</part>
-	</software>
-
-	<software name="msds330k">
-		<description>MS-Dos 3.30 (Knowledge Dynamics Corp)</description>
-		<year>1993</year>
-		<publisher>Knowledge Dynamics Corp,</publisher>
-		<part name="flop1" interface="floppy_5_25">
-			<feature name="disk_serial" value="02042 036214.330A" />
-			<feature name="disk_label" value="Programs" />
-			<dataarea name="flop" size="368640">
-				<rom name="disk 1.img" size="368640" crc="db07d99a" sha1="121ad3c636a69dae3a8eee96ef2ebf1152e9d00f" offset="0" />
+				<rom name="disk3a.img" size="1474560" crc="808b208d" sha1="06de13364e906c4ed69f19627ae0e682eb419078" offset="0" />
 			</dataarea>
 		</part>
-		<part name="flop2" interface="floppy_3_5">
-			<feature name="disk_serial" value="02043 036214.330A" />
-			<feature name="disk_label" value="Additional Pragrams and Microsoft GW-Basic Interpreter" />
-			<dataarea name="flop" size="368640">
-				<rom name="disk 2.img" size="368640" crc="bef8e643" sha1="97df57499e009101d04bd696d23024b4d220e297" offset="0" />
+		<part name="disk4" interface="floppy_3_5">
+			<dataarea name="flop" size="1474560">
+				<rom name="disk4a.img" size="1474560" crc="21b6d623" sha1="2f096a5d9cd00677de3aca30b01b52b24776c59a" offset="0" />
 			</dataarea>
 		</part>
 	</software>
 
-	<software name="msdos5m">
-		<description>MS-Dos 5.0 (Mecer OEM)</description>
-		<year>1991</year>
+	<software name="msdos622u" cloneof="msdos622">
+		<description>MS-DOS (Version 6.22, Upgrade, 3.5")</description>
+		<year>1994</year>
 		<publisher>Microsoft</publisher>
-		<info name="OEM" value="Mecer" />
+		<info name="version" value="6.22" />
 		<part name="flop1" interface="floppy_3_5">
-			<feature name="disk_serial" value="0044238" />
-			<dataarea name="flop" size="737280">
-				<rom name="operating 1.img" size="737280" crc="c54fe610" sha1="27756a10edbe33f76ff2239062af05dbfdc93979" offset="0" />
+			<dataarea name="flop" size="1474560">
+				<rom name="disk1u.img" size="1474560" crc="4b7d4093" sha1="3f18e0f833ab3c0a6e231f0dffd2cfd849b40c26" offset="0" />
 			</dataarea>
 		</part>
 		<part name="flop2" interface="floppy_3_5">
-			<feature name="disk_serial" value="0045925" />
-			<dataarea name="flop" size="737280">
-				<rom name="operating 2.img" size="737280" crc="9aa5c1a4" sha1="15cc58e267601b30a594372aea1ff3dbb73ea335" offset="0" />
+			<dataarea name="flop" size="1474560">
+				<rom name="disk2u.img" size="1474560" crc="8bd7688d" sha1="dfb44325e69e58393adfe8c911f709c63db0399c" offset="0" />
 			</dataarea>
 		</part>
 		<part name="flop3" interface="floppy_3_5">
-			<feature name="disk_serial" value="0044171" />
-			<dataarea name="flop" size="737280">
-				<rom name="operating 3.img" size="737280" crc="6248317a" sha1="c7ff3a04eb01cab3efb05b6b52ec8b8a36b9b269" offset="0" />
-			</dataarea>
-		</part>
-	</software>
-
-	<software name="dos5">
-		<description>MS-Dos 5.0 (5.25 Disks, RTM)</description>
-		<year>1991</year>
-		<publisher>Microsoft</publisher>
-		<info name="OEM" value="Mecer" />
-		<part name="flop1" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="disk 1.img" size="368640" crc="de9e3bf6" sha1="b78aaced6bf262a5aa7af6d328caaf8370539c7c" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop2" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="disk 2.img" size="368640" crc="b56623db" sha1="0424273d8b63a1d89a880c6737278bcf6003e5d5" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop3" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="disk 3.img" size="368640" crc="273b0fb7" sha1="79595c7831ffa5599f3682e7a9bf43c7b7620387" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop4" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="disk 4.img" size="368640" crc="69e4c763" sha1="af69f1c0e897a5f19c52941bc6e4fdbe4d17db6e" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop5" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="disk 5.img" size="368640" crc="3de11d76" sha1="b808a9b294b660454ddd84c014525052e6f9223e" offset="0" />
-			</dataarea>
-		</part>
-	</software>
-
-	<software name="dos5upg">
-		<description>MS-Dos 5.0 Upgrade (5.25 Disks, RTM)</description>
-		<year>1991</year>
-		<publisher>Microsoft</publisher>
-		<info name="OEM" value="Mecer" />
-		<part name="flop1" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="disk 1 (upgrade).img" size="368640" crc="01a3d9a2" sha1="083400723e475ed497b276c9d4f2799eff3b88b8" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop2" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="disk 2 (upgrade).img" size="368640" crc="a8709827" sha1="9dbbbd267eb9b63447ee04641892ff0bea08cd25" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop3" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="disk 3 (upgrade).img" size="368640" crc="bb5bb90b" sha1="5fd3b4fe686d7459b7048ec8f1a38860755a887a" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop4" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="disk 4 (upgrade).img" size="368640" crc="b411a21d" sha1="7623d0fa4b178415c1b85e8d14e452c5fa0a5bf0" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop5" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="disk 5 (upgrade).img" size="368640" crc="26edd0f6" sha1="87b38570250dd12b6b4e4f232d6d3f3ab7960d6c" offset="0" />
-			</dataarea>
-		</part>
-		<part name="flop6" interface="floppy_5_25">
-			<dataarea name="flop" size="368640">
-				<rom name="disk 6 (upgrade).img" size="368640" crc="782c0c4a" sha1="aaff65c8263ed44f7af69892a4b9c926ba0ccf75" offset="0" />
+			<dataarea name="flop" size="1474560">
+				<rom name="disk3u.img" size="1474560" crc="930f809d" sha1="cffa2e29b24d033218f73d1a4ba0b19f0a179316" offset="0" />
 			</dataarea>
 		</part>
 	</software>
 
-	<software name="msdos622up" cloneof="msdos622">
-		<description>MS-DOS 6.22 (Upgrade, Alt)</description>
+	<software name="msdos622ua" cloneof="msdos622">
+		<description>MS-DOS (Version 6.22, Upgrade, 3.5", Alt)</description>
 		<year>1994</year>
 		<publisher>Microsoft</publisher>
+		<info name="version" value="6.22" />
 		<part name="disk1" interface="floppy_3_5">
 			<dataarea name="flop" size="1474560">
 				<rom name="disk1up.img" size="1474560" crc="b4df72ec" sha1="b34723a322c380121101cbdace5f5ae66a71e97c" offset="0" />
@@ -1915,29 +1506,29 @@ Missing files come here
 		</part>
 	</software>
 
-	<software name="dos622" cloneof="msdos622">
-		<!-- from Acer CPR 1.2 recovery CD-ROM -->
-		<description>MS-DOS 6.22 (Alt)</description>
+	<software name="msdos622mu" cloneof="msdos622">
+		<description>MS-DOS (Version 6.22, Upgrade, 5.25")</description>
 		<year>1994</year>
 		<publisher>Microsoft</publisher>
-		<part name="disk1" interface="floppy_3_5">
-			<dataarea name="flop" size="1474560">
-				<rom name="disk1a.img" size="1474560" crc="69d8cfdd" sha1="30b4b2e99b26b0e5e7dbe61b9892e45fe751a3e8" offset="0" />
+		<info name="version" value="6.22" />
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size="1228800">
+				<rom name="disk1mu.img" size="1228800" crc="9519c473" sha1="1a2ca99b7ae94f21555326695cbb14a9a1898eee" offset="0" />
 			</dataarea>
 		</part>
-		<part name="disk2" interface="floppy_3_5">
-			<dataarea name="flop" size="1474560">
-				<rom name="disk2a.img" size="1474560" crc="76258952" sha1="1f268c5487f31982848461b9d628ef10b552c849" offset="0" />
+		<part name="flop2" interface="floppy_5_25">
+			<dataarea name="flop" size="1228800">
+				<rom name="disk2mu.img" size="1228800" crc="f70f29ab" sha1="f0a37131ba662ca3b8d0d0a291279497b533c156" offset="0" />
 			</dataarea>
 		</part>
-		<part name="disk3" interface="floppy_3_5">
-			<dataarea name="flop" size="1474560">
-				<rom name="disk3a.img" size="1474560" crc="808b208d" sha1="06de13364e906c4ed69f19627ae0e682eb419078" offset="0" />
+		<part name="flop3" interface="floppy_5_25">
+			<dataarea name="flop" size="1228800">
+				<rom name="disk3mu.img" size="1228800" crc="8980019f" sha1="ed14124c32e5075bad74729b2237bf9ef3e53e24" offset="0" />
 			</dataarea>
 		</part>
-		<part name="disk4" interface="floppy_3_5">
-			<dataarea name="flop" size="1474560">
-				<rom name="disk4.img" size="1474560" crc="21b6d623" sha1="2f096a5d9cd00677de3aca30b01b52b24776c59a" offset="0" />
+		<part name="flop4" interface="floppy_5_25">
+			<dataarea name="flop" size="1228800">
+				<rom name="disk4mu.img" size="1228800" crc="4d7453ab" sha1="f7063a4f9e129ac25013b6b3223e028d758f71aa" offset="0" />
 			</dataarea>
 		</part>
 	</software>
@@ -1945,9 +1536,10 @@ Missing files come here
 	<software name="msdos622sup" cloneof="msdos622">
 	<!-- Added Bad_Dump status, as questions remains on how they were dumped -->
 	<!-- Missing from this group: the 360kb Disk set-->
-		<description>MS-DOS 6.22 (Supplemental Disk)</description>
+		<description>MS-DOS (Version 6.22, Supplemental Disk)</description>
 		<year>1994</year>
 		<publisher>Microsoft</publisher>
+		<info name="version" value="6.22" />
 		<part name="disk1" interface="floppy_3_5">
 			<dataarea name="flop" size="1474560">
 				<rom name="disk 1 (1.4mb).img" size="1474560" crc="ac432292" sha1="a60876af212ffc9dd38529ee327adea4b10448f5" offset="0" status="baddump" />
@@ -3532,6 +3124,94 @@ Missing files come here
 		</part>
 	</software>
 
+	<software name="msbob">
+		<description>Bob (1.00a)</description>
+		<year>1995</year>
+		<publisher>Microsoft</publisher>
+		<info name="version" value="1.00a" />
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size = "1474560">
+				<rom name="disk01.img" size="1474560" crc="da78fa7d" sha1="6b45dc9310d534b9fb10fb5efcfaa5b5793a13e1" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_3_5">
+			<dataarea name="flop" size = "1720320">
+				<rom name="disk02.img" size="1720320" crc="833277a5" sha1="6966562977957fd28acdb98a53a4c6236be9aa20" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop3" interface="floppy_3_5">
+			<dataarea name="flop" size = "1720320">
+				<rom name="disk03.img" size="1720320" crc="60a7dda2" sha1="4b9e33275c6da0ee9b8a923e55a05d9281d335bf" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop4" interface="floppy_3_5">
+			<dataarea name="flop" size = "1720320">
+				<rom name="disk04.img" size="1720320" crc="b9c1ddc7" sha1="41a84750793826bc7033dc77ade621872f9101e0" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop5" interface="floppy_3_5">
+			<dataarea name="flop" size = "1720320">
+				<rom name="disk05.img" size="1720320" crc="ad765681" sha1="58df2e2602ff60d0da196d425c4e93bce4e6814f" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop6" interface="floppy_3_5">
+			<dataarea name="flop" size = "1720320">
+				<rom name="disk06.img" size="1720320" crc="e8be449d" sha1="f62f03bf86ee51937eaa05b528fdc96f71871c73" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop7" interface="floppy_3_5">
+			<dataarea name="flop" size = "1720320">
+				<rom name="disk07.img" size="1720320" crc="724f9922" sha1="89023ef479d843908ecd2d111ecd213b2d7bf420" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop8" interface="floppy_3_5">
+			<dataarea name="flop" size = "1720320">
+				<rom name="disk08.img" size="1720320" crc="25a88b00" sha1="f457a5ec85704a2d396e2d079a8f83977cf8bb04" offset="0"/>
+			</dataarea>
+		</part>
+	</software>
+
+	<software name="msboba" cloneof="msbob">
+		<description>Bob (1.00)</description>
+		<year>1995</year>
+		<publisher>Microsoft</publisher>
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size = "1474560">
+				<rom name="disk1.img" size="1474560" crc="98474db4" sha1="a16cd99600589a926ff62ea29bd8b4def25db439" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_3_5">
+			<dataarea name="flop" size = "1720320">
+				<rom name="disk2.img" size="1720320" crc="3b0b1462" sha1="e77be0b10daafa67bc48a3801b418e438794b158" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop3" interface="floppy_3_5">
+			<dataarea name="flop" size = "1720320">
+				<rom name="disk3.img" size="1720320" crc="c802bb17" sha1="a1356fc392d33e8f59c7ac8242801a6392fe2e75" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop4" interface="floppy_3_5">
+			<dataarea name="flop" size = "1720320">
+				<rom name="disk4.img" size="1720320" crc="2d735e4a" sha1="1726e95359440b00658ce9e2ab975da225127035" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop5" interface="floppy_3_5">
+			<dataarea name="flop" size = "1720320">
+				<rom name="disk5.img" size="1720320" crc="cb1a20ac" sha1="1581a17050c22a5267a007af6321b3e17b95302f" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop6" interface="floppy_3_5">
+			<dataarea name="flop" size = "1720320">
+				<rom name="disk6.img" size="1720320" crc="94bf0f1d" sha1="e49a8a155c51354675cdc0272a409657fed3e251" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop7" interface="floppy_3_5">
+			<dataarea name="flop" size = "1720320">
+				<rom name="disk7.img" size="1720320" crc="afb0e89c" sha1="cd456a4304f4dafa27d869350d3f713cc934beb4" offset="0"/>
+			</dataarea>
+		</part>
+	</software>
+
 	<software name="buttons" supported="no">
 		<!-- from Acer CPR 1.2 recovery CD-ROM -->
 		<description>Buttons for DOS (Shareware)</description>
@@ -3545,6 +3225,19 @@ Missing files come here
 		</part>
 	</software>
 
+	<software name="xmas4win">
+		<description>Christmas For Windows</description>
+		<year>1995</year>
+		<publisher>TDA Help!</publisher>
+		<info name="developer" value="Sygenex" />
+		<info name="version" value="3.0" />
+		<part name="flop1" interface="floppy_3_5">
+			<dataarea name="flop" size = "1474560">
+				<rom name="Xmas4Windows.img" size="1474560" crc="617a3326" sha1="72c78772e988f2c4cc9d0a0498ecfa847594c3b9" offset="0"/>
+			</dataarea>
+		</part>
+	</software>
+
 	<software name="comit" supported="no">
 		<!-- from Acer CPR 1.2 recovery CD-ROM -->
 		<description>COMit-LITE</description>
@@ -3558,8 +3251,8 @@ Missing files come here
 		</part>
 	</software>
 
-	<software name="dos7demo">
-		<description>IBM PC-Dos 7 (Demonstration)</description>
+	<software name="pcdos7d">
+		<description>PC DOS 7 (Demonstration)</description>
 		<year>1994</year>
 		<publisher>IBM</publisher>
 		<part name="flop1" interface="floppy_3_5">
@@ -3598,6 +3291,19 @@ Missing files come here
 		</part>
 	</software>
 
+	<software name="vrplyhse">
+		<!-- Dumped via Kryoflux, shows as good and unmodified -->
+		<description>Virtual Reality Playhouse (Cover disk)</description>
+		<year>1992</year>
+		<publisher>The Waite Group</publisher>
+		<info name="isbn" value="1878739190" />
+		<part name="flop1" interface="floppy_5_25">
+			<dataarea name="flop" size = "1228800">
+				<rom name="virtual reality playhouse.img" size="1228800" crc="f72fbdf9" sha1="bdf98003350b40f887f594de653a18fb391b6e98" offset="0"/>
+			</dataarea>
+		</part>
+	</software>
+
 	<software name="wdel3">
 		<description>WinDelete 3.0</description>
 		<year>1996</year>
@@ -3611,6 +3317,72 @@ Missing files come here
 		</part>
 	</software>
 
+	<software name="winword1">
+		<description>Word for Windows 1.0</description>
+		<year>1989</year>
+		<publisher>Microsoft</publisher>
+		<part name="flop1" interface="floppy_3_5">
+			<feature name="part_id" value="Setup" />
+			<dataarea name="flop" size = "737280">
+				<rom name="setup.img" size="737280" crc="553cb9fa" sha1="c618d0a7714007b9b971bc63c4d2deaea56fdb07" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop2" interface="floppy_3_5">
+			<feature name="part_id" value="Program" />
+			<dataarea name="flop" size = "737280">
+				<rom name="progrm.img" size="737280" crc="daa346c4" sha1="8fe7bced3d817788614d55747d7452154d3b37e0" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop3" interface="floppy_3_5">
+			<feature name="part_id" value="Conversions 1" />
+			<dataarea name="flop" size = "737280">
+				<rom name="conver.img" size="737280" crc="85875a14" sha1="45f5f33caa485c76b671ba72a34a49fa9c52ee2e" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop4" interface="floppy_3_5">
+			<feature name="part_id" value="Conversions 2" />
+			<dataarea name="flop" size = "737280">
+				<rom name="convr2.img" size="737280" crc="416fc793" sha1="30d46e6a6568c6aefca33d5223a1afd2b4055932" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop5" interface="floppy_3_5">
+			<feature name="part_id" value="Utilities 1" />
+			<dataarea name="flop" size = "737280">
+				<rom name="util1.img" size="737280" crc="64e30b02" sha1="06c0886543e4289474fc5549ecd0d8d986c08339" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop6" interface="floppy_3_5">
+			<feature name="part_id" value="Utilities 2" />
+			<dataarea name="flop" size = "737280">
+				<rom name="util2.img" size="737280" crc="27e4a32f" sha1="c2fb011041e7c1f06ea2be3746593413c44bbbdf" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop7" interface="floppy_3_5">
+			<feature name="part_id" value="Tutorial 1" />
+			<dataarea name="flop" size = "737280">
+				<rom name="tutrl1.img" size="737280" crc="808ccc36" sha1="87b8261827cfc0950f2d60a353ba73162cf5fd31" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop8" interface="floppy_3_5">
+			<feature name="part_id" value="Tutorial 2" />
+			<dataarea name="flop" size = "737280">
+				<rom name="tutrl2.img" size="737280" crc="426fc4b7" sha1="8e5295bcc11f63c0186ca7a0012550aaa751f632" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop9" interface="floppy_3_5">
+			<feature name="part_id" value="Help" />
+			<dataarea name="flop" size = "737280">
+				<rom name="help.img" size="737280" crc="d50900f3" sha1="9cd98aa432e38a6028fc1105e6ba5f24fe118d52" offset="0"/>
+			</dataarea>
+		</part>
+		<part name="flop10" interface="floppy_3_5">
+			<feature name="part_id" value="Proofing Tools" />
+			<dataarea name="flop" size = "737280">
+				<rom name="prftls.img" size="737280" crc="4610c528" sha1="2b64e4906e7ff2b7b8268c8f97e91ddd580f15c4" offset="0"/>
+			</dataarea>
+		</part>
+	</software>
+
 	<software name="wp60">
 		<description>WordPerfect 6.0 for DOS</description>
 		<year>1993</year>
diff --git a/hash/neogeo.xml b/hash/neogeo.xml
index cd36b82..3bf8348 100644
--- a/hash/neogeo.xml
+++ b/hash/neogeo.xml
@@ -979,9 +979,47 @@
 		</part>
 	</software>
 
+	<software name="burningfpa" cloneof="burningf">
+		<!-- later prototype - Sx, Vx and Cx data all matches final game, but with different rom arranagement, Px & Mx unique -->
+		<description>Burning Fight (prototype, ver 23.3, 910326)</description>
+		<year>1991</year>
+		<publisher>SNK</publisher>
+		<sharedfeat name="release" value="AES" />
+		<sharedfeat name="compatibility" value="MVS,AES" />
+		<part name="cart" interface="neo_cart">
+			<dataarea name="maincpu" width="16" endianness="big" size="0x100000">
+				<rom loadflag="load16_byte" name="018_p1_1f28.podd" offset="0x000001" size="0x080000" crc="f7d15752" sha1="334b7e5c8e9099d39424e72db66846d0b9e534de" />
+				<rom loadflag="load16_byte" name="018_p2_3217.peven" offset="0x000000" size="0x080000" crc="ffae22fb" sha1="82f2f81fe96b3c6953985964e12e93e79410ab9e" />
+			</dataarea>
+			<dataarea name="fixed" size="0x040000">
+				<rom offset="0x000000" size="0x020000" name="018_s1_4491.s1" crc="6799ea0d" sha1="ec75ef9dfdcb0b123574fc6d81ebaaadfba32fb5" />
+			</dataarea>
+			<dataarea name="audiocpu" size="0x020000">
+				<rom offset="0x000000" size="0x020000" name="018_m1_d13e.m1" crc="2b0c0415" sha1="a5a0d5e3ea2ef77b6f5cd14f2907ab2f1aed76b7" />
+			</dataarea>
+			<dataarea name="ymsnd" size="0x200000">
+				<rom name="018_v11_6c00.v11" offset="0x000000" size="0x080000" crc="b55b9670" sha1="b0ff38b2dca1361ad155e90be3674dbea1c0a53c" />
+				<rom name="018_v12_8146.v12" offset="0x080000" size="0x080000" crc="a0bcf260" sha1="5d1f2613cf4a292557f37e6f44a90b20d11ed8cd" />
+				<rom name="018_v13_b813.v13" offset="0x100000" size="0x080000" crc="270f4707" sha1="29e763acc9fd4b94d8b5d0ad917e20d8a66bbe49" />
+				<rom name="018_v24_22ee.v24" offset="0x180000" size="0x080000" crc="924e3d69" sha1="927091f9a098f00eb303f5567f4ee926bcb170e3" />
+			</dataarea>
+			<dataarea name="sprites" size="0x400000">
+				<!-- note, load32_byte -->
+				<rom loadflag="load32_byte" name="018_c1_2505.c11" offset="0x000000" size="0x080000" crc="3a441c6a" sha1="0347d47a689af67426be42b4c99da101ee01ce11" />
+				<rom loadflag="load32_byte" name="018_c2_3f55.c12" offset="0x000002" size="0x080000" crc="bb72404b" sha1="7620fccc50ecacf732bb1382abef42212d369f8c" />
+				<rom loadflag="load32_byte" name="018_c3_a20d.c13" offset="0x000001" size="0x080000" crc="87bffd2f" sha1="0f7c835029a3f561861a1a07987dad23a32a899c" />
+				<rom loadflag="load32_byte" name="018_c4_c6e1.c14" offset="0x000003" size="0x080000" crc="33803163" sha1="888ba63618a2ca541883a612f0c75ffa96f1c528" />
+				<rom loadflag="load32_byte" name="018_c5_2cd1.c15" offset="0x200000" size="0x080000" crc="74391952" sha1="0f7451ff74901e7250214a7604a37add56ad7e1f" />
+				<rom loadflag="load32_byte" name="018_c6_8135.c16" offset="0x200002" size="0x080000" crc="95e220e6" sha1="cef4f7c697ab6d20e1b5c85df773d0f1a79e3008" />
+				<rom loadflag="load32_byte" name="018_c7_d009.c17" offset="0x200001" size="0x080000" crc="41326c0d" sha1="64bbecb560d2795ae5292776604ea318a9ae53a6" />
+				<rom loadflag="load32_byte" name="018_c8_dc63.c18" offset="0x200003" size="0x080000" crc="ed3b1f04" sha1="0cb0d30e294e7ff398d553d0f08befb53ac65269" />
+			</dataarea>
+		</part>
+	</software>
+
 	<software name="burningfp" cloneof="burningf">
 		<!-- early prototype - all roms were hand labeled with CRCs, dumps verified against them -->
-		<description>Burning Fight (prototype)</description>
+		<description>Burning Fight (prototype, older)</description>
 		<year>1991</year>
 		<publisher>SNK</publisher>
 		<sharedfeat name="release" value="AES" />
@@ -4754,6 +4792,43 @@
 		</part>
 	</software>
 
+	<software name="rbff1k" cloneof="rbff1">
+		<description>Real Bout Fatal Fury / Real Bout Garou Densetsu (Korean release)</description>
+		<year>1995</year>
+		<publisher>SNK</publisher>
+		<info name="serial" value="NGM-095 (MVS), NGH-095 (AES)"/>
+		<info name="release" value="19951221 (MVS), 19960126 (AES)"/>
+		<info name="alt_title" value="リアルバウト 餓狼伝説"/>
+		<sharedfeat name="release" value="MVS,AES" />
+		<sharedfeat name="compatibility" value="MVS,AES" />
+		<part name="cart" interface="neo_cart">
+			<dataarea name="maincpu" width="16" endianness="big" size="0x300000">
+				<rom loadflag="load16_word_swap" name="095-p1k.p1" offset="0x000000" size="0x100000" crc="f705364b" sha1="2668e15663a2c7ec7396f40e4f5f454505968ce8" />   <!-- TC538200 -->
+				<rom loadflag="load16_word_swap" name="095-p2.sp2" offset="0x100000" size="0x200000" crc="cc15826e" sha1="44d6ac6c0ca697a6f367dcfd809b1e1771cb0635" />  <!-- TC5316200 -->
+			</dataarea>
+			<dataarea name="fixed" size="0x040000">
+				<rom offset="0x000000" size="0x020000" name="095-s1.s1" crc="b6bf5e08" sha1="b527355c35ea097f3448676f2ffa65b8e56ae30c" />   <!-- TC531000 -->
+			</dataarea>
+			<dataarea name="audiocpu" size="0x020000">
+				<rom offset="0x000000" size="0x020000" name="095-m1.m1" crc="653492a7" sha1="39e511fb9ed5d2135dc8428a31d0baafb2ab36e0" />   <!-- TC531001 -->
+			</dataarea>
+			<dataarea name="ymsnd" size="0xc00000">
+				<rom name="069-v1.v1" offset="0x000000" size="0x400000" crc="2bdbd4db" sha1="5f4fecf69c2329d699cbd45829c19303b1e2a80e" />   <!-- TC5332204 -->
+				<rom name="069-v2.v2" offset="0x400000" size="0x400000" crc="a698a487" sha1="11b8bc53bc26a51f4a408e900e3769958625c4ed" />   <!-- TC5332204 -->
+				<rom name="095-v3.v3" offset="0x800000" size="0x400000" crc="189d1c6c" sha1="f0b8cd1ee40ea3feeb2800f0723b451ec8240203" />   <!-- TC5332201 -->
+			</dataarea>
+			<dataarea name="sprites" size="0x1c00000">
+				<rom loadflag="load16_byte" name="069-c1.c1" offset="0x000000" size="0x400000" crc="e302f93c" sha1="d8610b14900b2b8fe691b67ca9b1abb335dbff74" />    <!-- TC5332205 -->
+				<rom loadflag="load16_byte" name="069-c2.c2" offset="0x000001" size="0x400000" crc="1053a455" sha1="69501bfac68739e63d798045b812badd251d57b8" />    <!-- TC5332205 -->
+				<rom loadflag="load16_byte" name="069-c3.c3" offset="0x800000" size="0x400000" crc="1c0fde2f" sha1="cf6c2ef56c03a861de3b0b6dc0d7c9204d947f9d" />    <!-- TC5332205 -->
+				<rom loadflag="load16_byte" name="069-c4.c4" offset="0x800001" size="0x400000" crc="a25fc3d0" sha1="83cb349e2f1032652060b233e741fb893be5af16" />    <!-- TC5332205 -->
+				<rom loadflag="load16_byte" name="095-c5.c5" offset="0x1000000" size="0x400000" crc="8b9b65df" sha1="e2a7e20855501f240bcd22f5cc92fcb4a9806abe" />   <!-- TC5332202 -->
+				<rom loadflag="load16_byte" name="095-c6.c6" offset="0x1000001" size="0x400000" crc="3e164718" sha1="53217f938c8964c1ca68a6fd5249c4169a5ac8e6" />   <!-- TC5332202 -->
+				<rom loadflag="load16_byte" name="095-c7.c7" offset="0x1800000" size="0x200000" crc="ca605e12" sha1="5150b835247fd705bc1dece97d423d9c20a51416" />   <!-- TC5316200 -->
+				<rom loadflag="load16_byte" name="095-c8.c8" offset="0x1800001" size="0x200000" crc="4e6beb6c" sha1="c0ac7cfc832ace6ad52c58f5da3a8101baead749" />   <!-- TC5316200 -->
+			</dataarea>
+		</part>
+	</software>
 
 	<!--
 	ID-0096
diff --git a/hash/pcw.xml b/hash/pcw.xml
index a2ac89f..654f446 100644
--- a/hash/pcw.xml
+++ b/hash/pcw.xml
@@ -1512,16 +1512,18 @@
 		</part>
 	</software>
 
-	<software name="sirlance">
-		<description>Sir Lancelot (Spa)</description>
-		<year>1985</year>
-		<publisher>OMK</publisher>
-		<part name="flop1" interface="floppy_3">
-			<dataarea name="flop" size="194816">
-				<rom name="sirlancelot_pcw.dsk" size="194816" crc="c47fb488" sha1="18d09cab70d50e0e9b2682ea751258fa47841120" offset="0" />
-			</dataarea>
-		</part>
-	</software>
+<!--
+    <software name="sirlance">
+        <description>Sir Lancelot (Spa)</description>
+        <year>1985</year>
+        <publisher>OMK</publisher>
+        <part name="flop1" interface="floppy_3">
+            <dataarea name="flop" size="194816">
+                <rom name="sirlancelot_pcw.dsk" size="194816" crc="c47fb488" sha1="18d09cab70d50e0e9b2682ea751258fa47841120" offset="0" />
+            </dataarea>
+        </part>
+    </software>
+-->
 
 	<software name="sirperce">
 		<description>Sir Perceval (Spa)</description>
diff --git a/hlsl/phosphor.fx b/hlsl/phosphor.fx
index 7d665b4..d78473a 100644
--- a/hlsl/phosphor.fx
+++ b/hlsl/phosphor.fx
@@ -94,19 +94,23 @@ VS_OUTPUT vs_main(VS_INPUT Input)
 //-----------------------------------------------------------------------------
 
 uniform float3 Phosphor = float3(0.0f, 0.0f, 0.0f);
+uniform float DeltaTime = 0.0f;
+static const float F = 30.0f;
 
 float4 ps_main(PS_INPUT Input) : COLOR
 {
 	float4 CurrPix = tex2D(DiffuseSampler, Input.TexCoord);
-	float3 PrevPix = tex2D(PreviousSampler, Input.PrevCoord).rgb * float3(Phosphor.r, Phosphor.g, Phosphor.b);
+	float3 PrevPix = tex2D(PreviousSampler, Input.PrevCoord).rgb;
 
+	PrevPix.r *= Phosphor.r == 0 ? 0 : pow(Phosphor.r, F * DeltaTime);
+	PrevPix.g *= Phosphor.g == 0 ? 0 : pow(Phosphor.g, F * DeltaTime);
+	PrevPix.b *= Phosphor.b == 0 ? 0 : pow(Phosphor.b, F * DeltaTime);
 	float RedMax = max(CurrPix.r, PrevPix.r);
 	float GreenMax = max(CurrPix.g, PrevPix.g);
 	float BlueMax = max(CurrPix.b, PrevPix.b);
 
-	return Passthrough
-		? CurrPix
-		: float4(RedMax, GreenMax, BlueMax, CurrPix.a);
+	return Passthrough ?
+	       CurrPix : float4(RedMax, GreenMax, BlueMax, CurrPix.a);
 }
 
 //-----------------------------------------------------------------------------
diff --git a/language/Catalan/strings.po b/language/Catalan/strings.po
index 27f2776..3638425 100644
--- a/language/Catalan/strings.po
+++ b/language/Catalan/strings.po
@@ -5,10 +5,10 @@
 #
 msgid ""
 msgstr ""
-"Project-Id-Version: MAME 0.176\n"
+"Project-Id-Version: MAME 0.180\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2016-08-29 01:56+1000\n"
-"PO-Revision-Date: 2016-07-29 10:13+0200\n"
+"PO-Revision-Date: 2016-12-14 14:01+0100\n"
 "Last-Translator: Jordi Mallach <jordi at debian.org>\n"
 "Language-Team: Catalan <ca at dodds.net>\n"
 "Language: ca\n"
@@ -638,29 +638,29 @@ msgstr "No es pot desar damunt d'un directori"
 msgid ""
 "The software selected is missing one or more required ROM or CHD images. "
 "Please select a different one."
-msgstr ""
+msgstr "El programari seleccionat manca una o més imatges ROM o CHD. Seleccioneu-ne un diferent."
 
 #: src/frontend/mame/ui/info.cpp:87
 msgid ""
 "One or more ROMs/CHDs for this machine are incorrect. The machine may not "
 "run correctly.\n"
-msgstr ""
+msgstr "Una o més ROM/CHD per a aquesta màquina són incorrectes. La màquina podria no executar-se correctament.\n"
 
 #: src/frontend/mame/ui/info.cpp:100
 msgid ""
 "There are known problems with this machine\n"
 "\n"
-msgstr ""
+msgstr "Hi ha problemes coneguts amb aquesta màquina\n\n"
 
 #: src/frontend/mame/ui/info.cpp:104
 msgid ""
 "One or more ROMs/CHDs for this machine have not been correctly dumped.\n"
-msgstr ""
+msgstr "Una o més ROM/CHD per a aquesta màquina no han estat bolcats correctament.\n"
 
 #: src/frontend/mame/ui/info.cpp:108
 #, c-format
 msgid "The keyboard emulation may not be 100% accurate.\n"
-msgstr ""
+msgstr "L'emulació del teclat pot no ser 100% acurada.\n"
 
 #: src/frontend/mame/ui/info.cpp:110
 #, c-format
@@ -669,17 +669,17 @@ msgstr "Els colors no són 100% acurats.\n"
 
 #: src/frontend/mame/ui/info.cpp:112
 msgid "The colors are completely wrong.\n"
-msgstr ""
+msgstr "Els colors estan completament malament.\n"
 
 #: src/frontend/mame/ui/info.cpp:114
 #, c-format
 msgid "The video emulation isn't 100% accurate.\n"
-msgstr ""
+msgstr "L'emulació de vídeo no és 100% acurada.\n"
 
 #: src/frontend/mame/ui/info.cpp:116
 #, c-format
 msgid "The sound emulation isn't 100% accurate.\n"
-msgstr ""
+msgstr "L'emulació de so no és 100% acurada.\n"
 
 #: src/frontend/mame/ui/info.cpp:118
 msgid "The machine lacks sound.\n"
@@ -691,7 +691,7 @@ msgstr ""
 
 #: src/frontend/mame/ui/info.cpp:125
 msgid "The machine requires external artwork files\n"
-msgstr ""
+msgstr "La màquina requereix fitxer d'art externs\n"
 
 #: src/frontend/mame/ui/info.cpp:130
 msgid ""
@@ -715,7 +715,7 @@ msgid ""
 "THIS MACHINE DOESN'T WORK. The emulation for this machine is not yet "
 "complete. There is nothing you can do to fix this problem except wait for "
 "the developers to improve the emulation.\n"
-msgstr ""
+msgstr "\nAQUESTA MÀQUINA NO FUNCIONA. L'emulació per a aquesta màquina no és completa. No podeu fer res al respecte, tret d'esperar a que els desenvolupadors milloren l'emulació.\n"
 
 #: src/frontend/mame/ui/info.cpp:150
 msgid ""
@@ -730,14 +730,14 @@ msgid ""
 "\n"
 "\n"
 "There are working clones of this machine: "
-msgstr ""
+msgstr "\n\nHi ha clons funcionals d'aquesta màquina: "
 
 #: src/frontend/mame/ui/info.cpp:183
 msgid ""
 "\n"
 "\n"
 "Press any key to continue"
-msgstr ""
+msgstr "\n\nPremeu qualsevol tecla per continuar"
 
 #: src/frontend/mame/ui/info.cpp:197
 #, c-format
@@ -748,6 +748,11 @@ msgid ""
 "\n"
 "CPU:\n"
 msgstr ""
+"%1$s\n"
+"%2$s %3$s\n"
+"Controlador: %4$s\n"
+"\n"
+"CPU:\n"
 
 #: src/frontend/mame/ui/info.cpp:232 src/frontend/mame/ui/info.cpp:270
 msgid "MHz"
@@ -1014,22 +1019,22 @@ msgstr "S'ha desat %s.txt sota la carpeta ui."
 
 #: src/frontend/mame/ui/miscmenu.cpp:667
 msgid "Export list in XML format (like -listxml)"
-msgstr ""
+msgstr "Exporta la llista en format XML (like -listxml)"
 
 #: src/frontend/mame/ui/miscmenu.cpp:668
 msgid "Export list in XML format (like -listxml, but exclude devices)"
-msgstr ""
+msgstr "Exporta la llista en format XML (com -listxml, però excloent dispositius)"
 
 #: src/frontend/mame/ui/miscmenu.cpp:669
 msgid "Export list in TXT format (like -listfull)"
-msgstr ""
+msgstr "Exporta la llista en format TXT (com -listfull)"
 
 #: src/frontend/mame/ui/miscmenu.cpp:719 src/frontend/mame/ui/ui.cpp:2315
 msgid ""
 "\n"
 "    Configuration saved    \n"
 "\n"
-msgstr ""
+msgstr "\n    S'ha desat la configuració    \n"
 
 #: src/frontend/mame/ui/miscmenu.cpp:766
 msgid "Bios"
@@ -1140,6 +1145,9 @@ msgid ""
 "\n"
 "Press any key to continue."
 msgstr ""
+"La màquina seleccionada manca una o més imatges ROM o CHD. Seleccioneu una altra màquina.\n"
+"\n"
+"Premeu una tecla per continuar."
 
 #: src/frontend/mame/ui/selgame.cpp:610
 #: src/frontend/mame/ui/simpleselgame.cpp:270
@@ -1301,7 +1309,7 @@ msgstr "No hi ha infos disponibles"
 #: src/frontend/mame/ui/selgame.cpp:1994
 #, c-format
 msgid "%1$s %2$s ( %3$d / %4$d machines (%5$d BIOS) )"
-msgstr ""
+msgstr "%1$s %2$s (%3$d / %4$d màquines (%5$d BIOS))"
 
 #: src/frontend/mame/ui/selgame.cpp:2004
 #, c-format
@@ -1448,6 +1456,9 @@ msgid ""
 "\n"
 "Press any key to continue."
 msgstr ""
+"El programari seleccionat manca un o més fitxers requerits. Seleccioneu un programari diferent.\n"
+"\n"
+"Premeu una tecla per continuar."
 
 #: src/frontend/mame/ui/selsoft.cpp:1478 src/frontend/mame/ui/selsoft.cpp:1498
 msgid "Software part selection:"
@@ -1460,7 +1471,7 @@ msgstr "Selecció de BIOS:"
 #: src/frontend/mame/ui/selsoft.cpp:1659
 #, c-format
 msgid "%1$s %2$s ( %3$d / %4$d software packages )"
-msgstr ""
+msgstr "%1$s %2$s (%3$d / %4$d paquets de programari)"
 
 #: src/frontend/mame/ui/selsoft.cpp:1660
 #, c-format
diff --git a/makefile b/makefile
index f342c48..3d55d51 100644
--- a/makefile
+++ b/makefile
@@ -217,6 +217,10 @@ endif
 # build scripts will be run from
 # scripts/target/$(TARGET)/$(SUBTARGET).lua
 #-------------------------------------------------
+ifdef PROJECT
+PARAMS += --PROJECT='$(PROJECT)'
+TARGET := $(PROJECT)
+endif
 
 ifndef TARGET
 TARGET := mame
@@ -800,8 +804,12 @@ SCRIPTS += scripts/target/$(TARGET)/mess.lua
 endif
 
 ifndef SOURCES
+ifdef PROJECT
+SCRIPTS += projects/$(PROJECT)/scripts/target/$(TARGET)/$(SUBTARGET_FULL).lua
+else
 SCRIPTS += scripts/target/$(TARGET)/$(SUBTARGET_FULL).lua
 endif
+endif
 
 ifdef REGENIE
 SCRIPTS+= regenie
@@ -1527,14 +1535,14 @@ endif
 
 ifeq (posix,$(SHELLTYPE))
 $(GENDIR)/version.cpp: $(GENDIR)/git_desc | $(GEN_FOLDERS)
-	@echo '#define BARE_BUILD_VERSION "0.180"' > $@
+	@echo '#define BARE_BUILD_VERSION "0.181"' > $@
 	@echo 'extern const char bare_build_version[];' >> $@
 	@echo 'extern const char build_version[];' >> $@
 	@echo 'const char bare_build_version[] = BARE_BUILD_VERSION;' >> $@
 	@echo 'const char build_version[] = BARE_BUILD_VERSION " ($(NEW_GIT_VERSION))";' >> $@
 else
 $(GENDIR)/version.cpp: $(GENDIR)/git_desc
-	@echo #define BARE_BUILD_VERSION "0.180" > $@
+	@echo #define BARE_BUILD_VERSION "0.181" > $@
 	@echo extern const char bare_build_version[]; >> $@
 	@echo extern const char build_version[]; >> $@
 	@echo const char bare_build_version[] = BARE_BUILD_VERSION; >> $@
diff --git a/nl_examples/diode.c b/nl_examples/diode.c
new file mode 100644
index 0000000..9a2196c
--- /dev/null
+++ b/nl_examples/diode.c
@@ -0,0 +1,31 @@
+/*
+ * diode.c
+ *
+ */
+
+
+#include "netlist/devices/net_lib.h"
+
+NETLIST_START(diode)
+    /* Standard stuff */
+
+    CLOCK(clk, 1000) // 1000 Hz
+    SOLVER(Solver, 48)
+    ANALOG_INPUT(V5, 5)
+
+	//DIODE(D, "1N914")
+    DIODE(D, "D(IS=1e-15)")
+
+    RES(R, RES_K(10))
+    RES(R1, RES_K(10))
+
+    NET_C(clk, D.K)
+    NET_C(D.A, R.1)
+    NET_C(R.2, V5)
+    NET_C(R1.2, GND)
+    NET_C(R.1, R1.1)
+
+    LOG(logB, clk)
+    LOG(logC, D.A)
+
+NETLIST_END()
diff --git a/nl_examples/norton_opamp.c b/nl_examples/norton_opamp.c
new file mode 100644
index 0000000..b5d8665
--- /dev/null
+++ b/nl_examples/norton_opamp.c
@@ -0,0 +1,127 @@
+/*
+ * opamp.c
+ *
+ */
+
+
+#include "netlist/devices/net_lib.h"
+
+NETLIST_START(main)
+
+    /* Standard stuff */
+
+    CLOCK(clk, 10000) // 1000 Hz
+    SOLVER(Solver, 48000)
+    ANALOG_INPUT(V5, 5)
+    PARAM(Solver.ACCURACY, 1e-6)
+    PARAM(Solver.DYNAMIC_TS, 0)
+    PARAM(Solver.SOR_FACTOR, 1.0)
+    //PARAM(Solver.CONVERG, 1.0)
+    PARAM(Solver.GS_LOOPS, 5)
+    PARAM(Solver.GS_THRESHOLD, 5)
+
+    SUBMODEL(op1, opamp_fast)
+    /* Wired as non - inverting amplifier like in LM3900 datasheet */
+
+    RES(R1, 25000)
+    RES(R2, 100000)
+    RES(R3, 200000)
+    CAP(C1, CAP_U(0.05))
+
+    NET_C(clk, C1.1)
+    NET_C(C1.2, R1.1)
+
+    NET_C(op1.VM, GND)
+    NET_C(op1.VP, V5    )
+    NET_C(op1.PLUS, R1.2, R3.1)
+    NET_C(R3.2, V5)
+    //NET_C(R3.2, GND)
+    NET_C(op1.MINUS, R2.2)
+    NET_C(op1.OUT, R2.1)
+
+    RES(RL, 10000)
+    NET_C(RL.2, GND)
+    NET_C(RL.1, op1.OUT)
+
+    LOG(logX, op1.OUT)
+    LOG(logY, clk)
+NETLIST_END()
+
+NETLIST_START(opamp)
+
+    /* Opamp model from
+     *
+     * http://www.ecircuitcenter.com/Circuits/opmodel1/opmodel1.htm
+     *
+     * Bandwidth 10Mhz
+     *
+     */
+
+    /* Terminal definitions for calling netlists */
+
+    ALIAS(PLUS, G1.IP) // Positive input
+    ALIAS(MINUS, G2.IN) // Negative input
+    ALIAS(OUT, EBUF.OP) // Opamp output ...
+    ALIAS(VM, EBUF.ON)  // V- terminal
+    ALIAS(VP, DUMMY.I)  // V+ terminal
+
+    DUMMY_INPUT(DUMMY)
+
+    /* The opamp model */
+
+    CCCS(G1)
+    CCCS(G2)
+    //PARAM(G1.G, 100)  // typical OP-AMP amplification 100 * 1000 = 100000
+    PARAM(G1.G, 1000000)  // typical OP-AMP amplification 100 * 1000 = 100000
+    PARAM(G2.G, 1000000)  // typical OP-AMP amplification 100 * 1000 = 100000
+    RES(RP1, 1000)
+    CAP(CP1, 1.59e-6)   // <== change to 1.59e-3 for 10Khz bandwidth
+    VCVS(EBUF)
+    PARAM(EBUF.RO, 50)
+    PARAM(EBUF.G, 1)
+
+//    NET_C(EBUF.ON, GND)
+
+    NET_C(G1.ON, GND)
+    NET_C(G2.ON, GND)
+    NET_C(RP1.2, GND)
+    NET_C(CP1.2, GND)
+    NET_C(EBUF.IN, GND)
+
+    NET_C(G1.IN, G2.IP, GND)
+
+    NET_C(RP1.1, G1.OP)
+    NET_C(RP1.1, G2.OP)
+    NET_C(CP1.1, RP1.1)
+    NET_C(EBUF.IP, RP1.1)
+
+NETLIST_END()
+
+NETLIST_START(opamp_fast)
+
+    /*
+     *  Fast norton opamp model without bandwidth
+     */
+
+    /* Terminal definitions for calling netlists */
+
+    ALIAS(PLUS, R1.1) // Positive input
+    ALIAS(MINUS, R2.1) // Negative input
+    ALIAS(OUT, G1.OP) // Opamp output ...
+    ALIAS(VM, G1.ON)  // V- terminal
+    ALIAS(VP, DUMMY.I)  // V+ terminal
+
+    DUMMY_INPUT(DUMMY)
+
+    /* The opamp model */
+
+    RES(R1, 1)
+    RES(R2, 1)
+    NET_C(R1.1, G1.IP)
+    NET_C(R2.1, G1.IN)
+    NET_C(R1.2, R2.2, G1.ON)
+    VCVS(G1)
+    PARAM(G1.G, 1000000)
+    PARAM(G1.RO, RES_K(8))
+
+NETLIST_END()
diff --git a/nl_examples/rc.c b/nl_examples/rc.c
new file mode 100644
index 0000000..1850da3
--- /dev/null
+++ b/nl_examples/rc.c
@@ -0,0 +1,31 @@
+/*
+ * cdelay.c
+ *
+ */
+
+#include "netlist/devices/net_lib.h"
+
+NETLIST_START(rc)
+
+    /*
+     * delay circuit
+     *
+     */
+
+    /* Standard stuff */
+
+    SOLVER(Solver, 48000)
+    PARAM(Solver.ACCURACY, 1e-6)
+    CLOCK(clk, 20000)
+
+    CAP(C1, 0.022e-6)
+    RES(R1, 10000)
+    RES(R2, 20000)
+
+    NET_C(clk, R2.1)
+    NET_C(R2.2, R1.1, C1.1)
+    NET_C(C1.2, R1.2, GND)
+
+    LOG(tt, C1.1)
+
+NETLIST_END()
diff --git a/nl_examples/rl.c b/nl_examples/rl.c
new file mode 100644
index 0000000..3b5056b
--- /dev/null
+++ b/nl_examples/rl.c
@@ -0,0 +1,32 @@
+/*
+ * lr.c
+ *
+ */
+
+#include "netlist/devices/net_lib.h"
+
+NETLIST_START(lr)
+
+    /*
+     * delay circuit
+     *
+     */
+
+    /* Standard stuff */
+
+    SOLVER(Solver, 48000)
+    PARAM(Solver.ACCURACY, 1e-6)
+    CLOCK(clk, 50)
+	PARAM(Solver.ITERATIVE, "MAT_CR")
+
+    IND(L1, 10)
+    RES(R1, 10000)
+  
+    NET_C(clk, L1.1)
+    NET_C(L1.2, R1.1)
+    NET_C(R1.2, GND)
+
+    //LOG(log_1, R1.1)
+    //LOG(log_2, clk)
+
+NETLIST_END()
diff --git a/plugins/hiscore/hiscore.dat b/plugins/hiscore/hiscore.dat
index 5a55b8b..2d9b50d 100644
--- a/plugins/hiscore/hiscore.dat
+++ b/plugins/hiscore/hiscore.dat
@@ -70,6 +70,11 @@
 
 ;@s:1945kiii.cpp
 
+1945kiiin:
+1945kiiio:
+@:maincpu,program,100a2d,63,03,88
+
+
 ;*******1945k III
 1945kiii:
 @:maincpu,program,100a2d,63,03,88
@@ -97,6 +102,15 @@ undoukai:
 
 ;@s:8080bw.cpp
 
+cosmicin:
+@:maincpu,program,20f4,02,00,00
+
+
+ozmawarsmr:
+@:maincpu,program,2043,02,00,00
+@:maincpu,program,2023,01,01,01
+
+
 ;updated when start a game
 escmars:
 @:maincpu,program,20db,1,0a,0a
@@ -2413,6 +2427,10 @@ circusce:
 
 ;@s:cischeat.cpp
 
+f1gpstaro:
+@:cpu1,program,f2803,5e3,04,4d
+
+
 ;(big run (11th rallye version))
 bigrun:
 @:cpu1,program,f61da,2bc,50,05
@@ -3045,11 +3063,12 @@ rockmanj:
 
 forgottn:
 forgottnu:
-forgottnu1:
 forgottnua:
 forgottnuaa:
 lostwrld:
 lostwrldo:
+forgottnuc:
+forgottnue:
 @:maincpu,program,ffe142,50,00,20
 @:maincpu,program,ffb2a0,04,00,00
 
@@ -3932,9 +3951,9 @@ stoffyu:
 ;wwfwfestb:******www wrestlefest (us bootleg)
 ;wwfwfesta:******www wrestlefest (us tecmo)
 wwfwfest:
-wwfwfesta:
 wwfwfestb:
 wwfwfestj:
+wwfwfestu:
 @:maincpu,program,1c00c2,84,08,01
 
 
@@ -6707,6 +6726,11 @@ hvyunitu:
 
 ;@s:hyperspt.cpp
 
+roadf3:
+@:maincpu,program,3bd0,10a,01,01
+@:maincpu,program,3066,3,01,00
+
+
 roadf:
 roadf2:
 @:maincpu,program,3bd0,10a,01,01
@@ -8873,6 +8897,10 @@ mnchmobl:
 
 ;@s:mustache.cpp
 
+mustachei:
+@:maincpu,program,f000,50,00,47
+
+
 ;*******mustache boy
 mustache:
 @:maincpu,program,f000,50,00,47
@@ -8880,6 +8908,10 @@ mustache:
 
 ;@s:mw8080bw.cpp
 
+blueshrkmr:
+@:maincpu,program,200a,05,00,00
+
+
 lagunar:
 @:maincpu,program,2011,9,00,00
 @:maincpu,program,2005,3,00,00
@@ -10972,6 +11004,12 @@ btlkroadk:
 
 ;@s:psikyosh.cpp
 
+;(sol divide) (by Paul Priest)
+soldividk:
+@:maincpu,program,600bb50,18,00,50
+@:maincpu,program,600bb68,1e,24,02
+
+
 ;gunbarich (by tamphax)
 gnbarich:
 @:maincpu,program,6076864,a5,00,01
@@ -14425,6 +14463,14 @@ tail2nos:
 
 ;@s:taito_b.cpp
 
+;** you must wait untill the hiscore table has displayed in attract mode before **
+;** starting a game, for the save to work ** 
+hiticej:
+hiticerb:
+@:maincpu,program,802830,27,00,4b
+@:maincpu,program,802852,1,56,56
+
+
 crimec:
 crimecj:
 crimecu:
@@ -16606,6 +16652,10 @@ vastar4:
 
 ;@s:vendetta.cpp
 
+vendetta2pun:
+@:maincpu,program,2980,28,00,48
+
+
 vendetta:
 vendetta2p:
 vendetta2pd:
diff --git a/projects/README.md b/projects/README.md
new file mode 100644
index 0000000..c04bc3f
--- /dev/null
+++ b/projects/README.md
@@ -0,0 +1,4 @@
+# **Projects** #
+
+This is place where source code projects outside of MAME lives.
+Here you can git clone that kind of project and make it with "make PROJECT=example"
\ No newline at end of file
diff --git a/scripts/build/png2bdc.py b/scripts/build/png2bdc.py
index 4ffeb4c..a1be5c5 100644
--- a/scripts/build/png2bdc.py
+++ b/scripts/build/png2bdc.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python 
+#!/usr/bin/env python
 ##
 ## license:BSD-3-Clause
 ## copyright-holders:Aaron Giles, Andrew Gardner
@@ -50,7 +50,7 @@
 ##
 ## Python note:
 ##   This is a near-literal translation of the original C++ code.  As such there
-##   are some very non-pythonic things done throughout.  The conversion was done 
+##   are some very non-pythonic things done throughout.  The conversion was done
 ##   this way so as to insure compatibility as much as possible given the small
 ##   number of test cases.
 ##
@@ -74,7 +74,7 @@ class RenderFontChar:
     """
     Contains information about a single character in a font.
     """
-    
+
     def __init__(self):
         """
         """
@@ -90,10 +90,11 @@ class RenderFont:
     """
     Contains information about a font
     """
-    
+
     def __init__(self):
         self.height = 0         # height of the font, from ascent to descent
         self.yOffs = 0          # y offset from baseline to descent
+        self.defChar = -1       # default character for glyphs not present
         self.chars = list()     # array of characters
         for i in range(0, 65536):
             self.chars.append(RenderFontChar())
@@ -107,7 +108,7 @@ def pixelIsSet(value):
     return (value & 0xffffff) == 0
 
 
-def renderFontSaveCached(font, filename, hash32):
+def renderFontSaveCached(font, filename, length64, hash32):
     """
     """
     fp = open(filename, "wb")
@@ -120,45 +121,61 @@ def renderFontSaveCached(font, filename, hash32):
         if c.width > 0:
             numChars += 1
 
-    CACHED_CHAR_SIZE = 12
-    CACHED_HEADER_SIZE = 16
-    
+    CACHED_CHAR_SIZE = 16
+    CACHED_HEADER_SIZE = 32
+
     try:
+        fp.write(b'b')
+        fp.write(b'd')
+        fp.write(b'c')
         fp.write(b'f')
-        fp.write(b'o')
         fp.write(b'n')
         fp.write(b't')
+        fp.write(b2p(1))
+        fp.write(b2p(0))
+        fp.write(b2p(length64 >> 56 & 0xff))
+        fp.write(b2p(length64 >> 48 & 0xff))
+        fp.write(b2p(length64 >> 40 & 0xff))
+        fp.write(b2p(length64 >> 32 & 0xff))
+        fp.write(b2p(length64 >> 24 & 0xff))
+        fp.write(b2p(length64 >> 16 & 0xff))
+        fp.write(b2p(length64 >> 8 & 0xff))
+        fp.write(b2p(length64 >> 0 & 0xff))
         fp.write(b2p(hash32 >> 24 & 0xff))
         fp.write(b2p(hash32 >> 16 & 0xff))
         fp.write(b2p(hash32 >> 8 & 0xff))
         fp.write(b2p(hash32 >> 0 & 0xff))
-        fp.write(b2p(font.height >> 8 & 0xff))
-        fp.write(b2p(font.height >> 0 & 0xff))
-        fp.write(b2p(font.yOffs >> 8 & 0xff))
-        fp.write(b2p(font.yOffs >> 0 & 0xff))
         fp.write(b2p(numChars >> 24 & 0xff))
         fp.write(b2p(numChars >> 16 & 0xff))
         fp.write(b2p(numChars >> 8 & 0xff))
         fp.write(b2p(numChars >> 0 & 0xff))
-        
+        fp.write(b2p(font.height >> 8 & 0xff))
+        fp.write(b2p(font.height >> 0 & 0xff))
+        fp.write(b2p(font.yOffs >> 8 & 0xff))
+        fp.write(b2p(font.yOffs >> 0 & 0xff))
+        fp.write(b2p(font.defChar >> 24 & 0xff))
+        fp.write(b2p(font.defChar >> 16 & 0xff))
+        fp.write(b2p(font.defChar >> 8 & 0xff))
+        fp.write(b2p(font.defChar >> 0 & 0xff))
+
         # Write a blank table at first (?)
         charTable = [0]*(numChars * CACHED_CHAR_SIZE)
         for i in range(numChars * CACHED_CHAR_SIZE):
             fp.write(b2p(charTable[i]))
-        
+
         # Loop over all characters
         tableIndex = 0
-        
+
         for i in range(len(font.chars)):
             c = font.chars[i]
             if c.width == 0:
                 continue
-            
+
             if c.bitmap:
                 dBuffer = list()
                 accum = 0
                 accbit = 7
-    
+
                 # Bit-encode the character data
                 for y in range(0, c.bmHeight):
                     src = None
@@ -173,42 +190,44 @@ def renderFontSaveCached(font, filename, hash32):
                             dBuffer.append(accum)
                             accum = 0
                             accbit = 7
-                
+
                 # Flush any extra
                 if accbit != 7:
                     dBuffer.append(accum)
-                
+
                 # Write the data
                 for j in range(len(dBuffer)):
                     fp.write(b2p(dBuffer[j]))
-            
+
             destIndex = tableIndex * CACHED_CHAR_SIZE
-            charTable[destIndex +  0] = i >> 8 & 0xff
-            charTable[destIndex +  1] = i >> 0 & 0xff
-            charTable[destIndex +  2] = c.width >> 8 & 0xff
-            charTable[destIndex +  3] = c.width >> 0 & 0xff
-            charTable[destIndex +  4] = c.xOffs >> 8 & 0xff
-            charTable[destIndex +  5] = c.xOffs >> 0 & 0xff
-            charTable[destIndex +  6] = c.yOffs >> 8 & 0xff
-            charTable[destIndex +  7] = c.yOffs >> 0 & 0xff
-            charTable[destIndex +  8] = c.bmWidth >> 8 & 0xff
-            charTable[destIndex +  9] = c.bmWidth >> 0 & 0xff
-            charTable[destIndex + 10] = c.bmHeight >> 8 & 0xff
-            charTable[destIndex + 11] = c.bmHeight >> 0 & 0xff
+            charTable[destIndex +  0] = i >> 24 & 0xff
+            charTable[destIndex +  1] = i >> 16 & 0xff
+            charTable[destIndex +  2] = i >> 8 & 0xff
+            charTable[destIndex +  3] = i >> 0 & 0xff
+            charTable[destIndex +  4] = c.width >> 8 & 0xff
+            charTable[destIndex +  5] = c.width >> 0 & 0xff
+            charTable[destIndex +  8] = c.xOffs >> 8 & 0xff
+            charTable[destIndex +  9] = c.xOffs >> 0 & 0xff
+            charTable[destIndex + 10] = c.yOffs >> 8 & 0xff
+            charTable[destIndex + 11] = c.yOffs >> 0 & 0xff
+            charTable[destIndex + 12] = c.bmWidth >> 8 & 0xff
+            charTable[destIndex + 13] = c.bmWidth >> 0 & 0xff
+            charTable[destIndex + 14] = c.bmHeight >> 8 & 0xff
+            charTable[destIndex + 15] = c.bmHeight >> 0 & 0xff
             tableIndex += 1
-    
+
         # Seek back to the beginning and rewrite the table
         fp.seek(CACHED_HEADER_SIZE, 0)
         for i in range(numChars * CACHED_CHAR_SIZE):
             fp.write(b2p(charTable[i]))
-    
+
         fp.close()
         return 0
 
     except:
         print(sys.exc_info[1])
         return 1
-    
+
 
 def bitmapToChars(pngObject, font):
     """
@@ -225,7 +244,7 @@ def bitmapToChars(pngObject, font):
         for r,g,b,a in zip(irpd, irpd, irpd, irpd):
             cRow.append(a << 24 | r << 16 | g << 8 | b)
         bitmap.append(cRow)
-    
+
     rowStart = 0
     while rowStart < height:
         # Find the top of the row
@@ -317,7 +336,7 @@ def bitmapToChars(pngObject, font):
                 ch.yOffs = font.yOffs
                 ch.bmWidth = len(ch.bitmap[0])
                 ch.bmHeight = len(ch.bitmap)
-                
+
                 # Insert the character into the list
                 font.chars[chStart] = ch
 
@@ -327,7 +346,7 @@ def bitmapToChars(pngObject, font):
 
         # Next row
         rowStart = rowEnd + 1
-    
+
     # Return non-zero if we errored
     return rowStart < height
 
@@ -341,7 +360,7 @@ def main():
         sys.stderr.write("Usage:\n%s <input.png> [<input2.png> [...]] <output.bdc>\n" % sys.argv[0])
         return 1
     bdcName = sys.argv[-1]
-    
+
     font = RenderFont()
     for i in range(1, len(sys.argv)-1):
         filename = sys.argv[i]
@@ -359,12 +378,12 @@ def main():
     error = bitmapToChars(pngObject, font)
     if error:
         return 1
-    
-    error = renderFontSaveCached(font, bdcName, 0)
+
+    error = renderFontSaveCached(font, bdcName, 0, 0)
     return error
-    
-    
-    
+
+
+
 ########################################
 ## Program entry point
 ########################################
diff --git a/scripts/font/NotoSans-Bold.bdc b/scripts/font/NotoSans-Bold.bdc
index 8c13907..2ac5c7e 100644
Binary files a/scripts/font/NotoSans-Bold.bdc and b/scripts/font/NotoSans-Bold.bdc differ
diff --git a/scripts/genie.lua b/scripts/genie.lua
index 39669ac..e905e3b 100644
--- a/scripts/genie.lua
+++ b/scripts/genie.lua
@@ -386,6 +386,11 @@ newoption {
 	description = "Produce WebAssembly output when building with Emscripten.",
 }
 
+newoption {
+	trigger = "PROJECT",
+	description = "Select projects to be built. Will look into project folder for files.",
+}
+
 dofile ("extlib.lua")
 
 if _OPTIONS["SHLIB"]=="1" then
@@ -475,6 +480,7 @@ configuration { "vs*" }
 configuration { "Debug", "vs*" }
 	flags {
 		"Symbols",
+		"NoIncrementalLink",
 	}
 
 configuration { "Release", "vs*" }
@@ -515,7 +521,14 @@ msgprecompile ("Precompiling $(subst ../,,$<)...")
 
 messageskip { "SkipCreatingMessage", "SkipBuildingMessage", "SkipCleaningMessage" }
 
-if (_OPTIONS["SOURCES"] == nil) then
+if (_OPTIONS["PROJECT"] ~= nil) then
+	PROJECT_DIR = path.join(path.getabsolute(".."),"projects",_OPTIONS["PROJECT"]) .. "/"
+	if (not os.isfile(path.join("..", "projects", _OPTIONS["PROJECT"], "scripts", "target", _OPTIONS["target"],_OPTIONS["subtarget"] .. ".lua"))) then
+		error("File definition for TARGET=" .. _OPTIONS["target"] .. " SUBTARGET=" .. _OPTIONS["subtarget"] .. " does not exist")
+	end
+	dofile (path.join(".." ,"projects", _OPTIONS["PROJECT"], "scripts", "target", _OPTIONS["target"],_OPTIONS["subtarget"] .. ".lua"))
+end
+if (_OPTIONS["SOURCES"] == nil and _OPTIONS["PROJECT"] == nil) then
 	if (not os.isfile(path.join("target", _OPTIONS["target"],_OPTIONS["subtarget"] .. ".lua"))) then
 		error("File definition for TARGET=" .. _OPTIONS["target"] .. " SUBTARGET=" .. _OPTIONS["subtarget"] .. " does not exist")
 	end
@@ -1304,6 +1317,13 @@ configuration { "Debug", "gmake" }
 configuration { }
 
 if (_OPTIONS["SOURCES"] ~= nil) then
+	local str = _OPTIONS["SOURCES"]
+	for word in string.gmatch(str, '([^,]+)') do
+		if (not os.isfile(path.join(MAME_DIR ,word))) then
+			print("File " .. word.. " does not exist")
+			os.exit()
+		end
+	end
 	OUT_STR = os.outputof( PYTHON .. " " .. MAME_DIR .. "scripts/build/makedep.py " .. MAME_DIR .. " " .. _OPTIONS["SOURCES"] .. " target " .. _OPTIONS["subtarget"])
 	load(OUT_STR)()
 	os.outputof( PYTHON .. " " .. MAME_DIR .. "scripts/build/makedep.py " .. MAME_DIR .. " " .. _OPTIONS["SOURCES"] .. " drivers " .. _OPTIONS["subtarget"] .. " > ".. GEN_DIR  .. _OPTIONS["target"] .. "/" .. _OPTIONS["subtarget"]..".flt")
diff --git a/scripts/resources/uwp/mame_TemporaryKey.pfx b/scripts/resources/uwp/mame_TemporaryKey.pfx
new file mode 100644
index 0000000..de6ef5c
Binary files /dev/null and b/scripts/resources/uwp/mame_TemporaryKey.pfx differ
diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua
index 3039341..4af0e78 100644
--- a/scripts/src/bus.lua
+++ b/scripts/src/bus.lua
@@ -2416,6 +2416,7 @@ if (BUSES["COCO"]~=null) then
 		MAME_DIR .. "src/devices/bus/coco/coco_dwsock.cpp",
 		MAME_DIR .. "src/devices/bus/coco/coco_dwsock.h",
 		MAME_DIR .. "src/devices/bus/coco/dragon_fdc.cpp",
+		MAME_DIR .. "src/devices/bus/coco/coco_t4426.cpp",
 	}
 end
 
diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua
index 126d28e..af82ec7 100644
--- a/scripts/src/cpu.lua
+++ b/scripts/src/cpu.lua
@@ -13,7 +13,7 @@
 -- Dynamic recompiler objects
 --------------------------------------------------
 
-if (CPUS["SH2"]~=null or CPUS["MIPS"]~=null or CPUS["POWERPC"]~=null or CPUS["RSP"]~=null or CPUS["ARM7"]~=null or CPUS["ADSP21062"]~=null) then
+if (CPUS["SH2"]~=null or CPUS["MIPS"]~=null or CPUS["POWERPC"]~=null or CPUS["RSP"]~=null or CPUS["ARM7"]~=null or CPUS["ADSP21062"]~=null or CPUS["MB86235"]~=null) then
 	files {
 		MAME_DIR .. "src/devices/cpu/drcbec.cpp",
 		MAME_DIR .. "src/devices/cpu/drcbec.h",
@@ -1064,6 +1064,9 @@ if (CPUS["MB86235"]~=null) then
 	files {
 		MAME_DIR .. "src/devices/cpu/mb86235/mb86235.cpp",
 		MAME_DIR .. "src/devices/cpu/mb86235/mb86235.h",
+		MAME_DIR .. "src/devices/cpu/mb86235/mb86235drc.cpp",
+		MAME_DIR .. "src/devices/cpu/mb86235/mb86235fe.cpp",
+		MAME_DIR .. "src/devices/cpu/mb86235/mb86235fe.h",
 	}
 end
 
diff --git a/scripts/src/emu.lua b/scripts/src/emu.lua
index cd94d54..76cdb16 100644
--- a/scripts/src/emu.lua
+++ b/scripts/src/emu.lua
@@ -93,8 +93,6 @@ files {
 	MAME_DIR .. "src/emu/dislot.h",
 	MAME_DIR .. "src/emu/disound.cpp",
 	MAME_DIR .. "src/emu/disound.h",
-	MAME_DIR .. "src/emu/dispatch.cpp",
-	MAME_DIR .. "src/emu/dispatch.h",
 	MAME_DIR .. "src/emu/distate.cpp",
 	MAME_DIR .. "src/emu/distate.h",
 	MAME_DIR .. "src/emu/divideo.cpp",
@@ -183,7 +181,6 @@ files {
 	MAME_DIR .. "src/emu/video.h",
 	MAME_DIR .. "src/emu/rendersw.hxx",
 	MAME_DIR .. "src/emu/ui/uimain.h",
-	MAME_DIR .. "src/emu/ui/cmdrender.h", -- TODO: remove
 	MAME_DIR .. "src/emu/ui/cmddata.h",   -- TODO: remove
 	MAME_DIR .. "src/emu/debug/debugcmd.cpp",
 	MAME_DIR .. "src/emu/debug/debugcmd.h",
diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua
index 032c8f5..59a506c 100644
--- a/scripts/src/machine.lua
+++ b/scripts/src/machine.lua
@@ -357,6 +357,18 @@ end
 
 ---------------------------------------------------
 --
+-- at src/devices/machine/74157.h,MACHINES["TTL74157"] = true
+---------------------------------------------------
+
+if (MACHINES["TTL74157"]~=null) then
+	files {
+		MAME_DIR .. "src/devices/machine/74157.cpp",
+		MAME_DIR .. "src/devices/machine/74157.h",
+	}
+end
+
+---------------------------------------------------
+--
 -- at src/devices/machine/74161.h,MACHINES["TTL74161"] = true
 ---------------------------------------------------
 
@@ -659,6 +671,19 @@ end
 
 ---------------------------------------------------
 --
+-- at src/devices/machine/cdp1879.h,MACHINES["CDP1879"] = true
+---------------------------------------------------
+
+if (MACHINES["CDP1879"]~=null) then
+	files {
+		MAME_DIR .. "src/devices/machine/cdp1879.cpp",
+		MAME_DIR .. "src/devices/machine/cdp1879.h",
+	}
+end
+
+
+---------------------------------------------------
+--
 -- at src/devices/machine/com8116.h,MACHINES["COM8116"] = true
 ---------------------------------------------------
 
diff --git a/scripts/src/main.lua b/scripts/src/main.lua
index ccc0eb3..a78965a 100644
--- a/scripts/src/main.lua
+++ b/scripts/src/main.lua
@@ -276,8 +276,12 @@ end
 	links {
 		ext_lib("zlib"),
 		ext_lib("flac"),
+	}
+if (STANDALONE~=true) then
+	links {
 		ext_lib("sqlite3"),
 	}
+end
 
 	if _OPTIONS["NO_USE_MIDI"]~="1" then
 		links {
diff --git a/scripts/src/netlist.lua b/scripts/src/netlist.lua
index 70feb29..95b6a65 100644
--- a/scripts/src/netlist.lua
+++ b/scripts/src/netlist.lua
@@ -91,18 +91,30 @@ project "netlist"
 		MAME_DIR .. "src/lib/netlist/solver/nld_ms_w.h",
 		MAME_DIR .. "src/lib/netlist/solver/nld_ms_direct_lu.h",
 		MAME_DIR .. "src/lib/netlist/solver/vector_base.h",
+		MAME_DIR .. "src/lib/netlist/devices/nld_2102A.cpp",
+		MAME_DIR .. "src/lib/netlist/devices/nld_2102A.h",
+		MAME_DIR .. "src/lib/netlist/devices/nld_2716.cpp",
+		MAME_DIR .. "src/lib/netlist/devices/nld_2716.h",
 		MAME_DIR .. "src/lib/netlist/devices/nld_4020.cpp",
 		MAME_DIR .. "src/lib/netlist/devices/nld_4020.h",
 		MAME_DIR .. "src/lib/netlist/devices/nld_4066.cpp",
 		MAME_DIR .. "src/lib/netlist/devices/nld_4066.h",
+		MAME_DIR .. "src/lib/netlist/devices/nld_4316.cpp",
+		MAME_DIR .. "src/lib/netlist/devices/nld_4316.h",
 		MAME_DIR .. "src/lib/netlist/devices/nld_7448.cpp",
 		MAME_DIR .. "src/lib/netlist/devices/nld_7448.h",
 		MAME_DIR .. "src/lib/netlist/devices/nld_7450.cpp",
 		MAME_DIR .. "src/lib/netlist/devices/nld_7450.h",
+		MAME_DIR .. "src/lib/netlist/devices/nld_7473.cpp",
+		MAME_DIR .. "src/lib/netlist/devices/nld_7473.h",
 		MAME_DIR .. "src/lib/netlist/devices/nld_7474.cpp",
 		MAME_DIR .. "src/lib/netlist/devices/nld_7474.h",
+		MAME_DIR .. "src/lib/netlist/devices/nld_7475.cpp",
+		MAME_DIR .. "src/lib/netlist/devices/nld_7475.h",
 		MAME_DIR .. "src/lib/netlist/devices/nld_7483.cpp",
 		MAME_DIR .. "src/lib/netlist/devices/nld_7483.h",
+		MAME_DIR .. "src/lib/netlist/devices/nld_7485.cpp",
+		MAME_DIR .. "src/lib/netlist/devices/nld_7485.h",
 		MAME_DIR .. "src/lib/netlist/devices/nld_7490.cpp",
 		MAME_DIR .. "src/lib/netlist/devices/nld_7490.h",
 		MAME_DIR .. "src/lib/netlist/devices/nld_7493.cpp",
@@ -113,30 +125,56 @@ project "netlist"
 		MAME_DIR .. "src/lib/netlist/devices/nld_74123.h",
 		MAME_DIR .. "src/lib/netlist/devices/nld_74153.cpp",
 		MAME_DIR .. "src/lib/netlist/devices/nld_74153.h",
+		MAME_DIR .. "src/lib/netlist/devices/nld_74161.cpp",
+		MAME_DIR .. "src/lib/netlist/devices/nld_74161.h",
+		MAME_DIR .. "src/lib/netlist/devices/nld_74165.cpp",
+		MAME_DIR .. "src/lib/netlist/devices/nld_74165.h",
+		MAME_DIR .. "src/lib/netlist/devices/nld_74166.cpp",
+		MAME_DIR .. "src/lib/netlist/devices/nld_74166.h",
+		MAME_DIR .. "src/lib/netlist/devices/nld_74174.cpp",
+		MAME_DIR .. "src/lib/netlist/devices/nld_74174.h",
 		MAME_DIR .. "src/lib/netlist/devices/nld_74175.cpp",
 		MAME_DIR .. "src/lib/netlist/devices/nld_74175.h",
 		MAME_DIR .. "src/lib/netlist/devices/nld_74192.cpp",
 		MAME_DIR .. "src/lib/netlist/devices/nld_74192.h",
 		MAME_DIR .. "src/lib/netlist/devices/nld_74193.cpp",
 		MAME_DIR .. "src/lib/netlist/devices/nld_74193.h",
+		MAME_DIR .. "src/lib/netlist/devices/nld_74194.cpp",
+		MAME_DIR .. "src/lib/netlist/devices/nld_74194.h",
 		MAME_DIR .. "src/lib/netlist/devices/nld_74279.cpp",
 		MAME_DIR .. "src/lib/netlist/devices/nld_74279.h",
+		MAME_DIR .. "src/lib/netlist/devices/nld_74365.cpp",
+		MAME_DIR .. "src/lib/netlist/devices/nld_74365.h",
 		MAME_DIR .. "src/lib/netlist/devices/nld_74ls629.cpp",
 		MAME_DIR .. "src/lib/netlist/devices/nld_74ls629.h",
 		MAME_DIR .. "src/lib/netlist/devices/nld_82S16.cpp",
 		MAME_DIR .. "src/lib/netlist/devices/nld_82S16.h",
+		MAME_DIR .. "src/lib/netlist/devices/nld_82S115.cpp",
+		MAME_DIR .. "src/lib/netlist/devices/nld_82S115.h",
+		MAME_DIR .. "src/lib/netlist/devices/nld_82S123.cpp",
+		MAME_DIR .. "src/lib/netlist/devices/nld_82S123.h",
+		MAME_DIR .. "src/lib/netlist/devices/nld_82S126.cpp",
+		MAME_DIR .. "src/lib/netlist/devices/nld_82S126.h",
 		MAME_DIR .. "src/lib/netlist/devices/nld_9310.cpp",
 		MAME_DIR .. "src/lib/netlist/devices/nld_9310.h",
 		MAME_DIR .. "src/lib/netlist/devices/nld_9312.cpp",
 		MAME_DIR .. "src/lib/netlist/devices/nld_9312.h",
 		MAME_DIR .. "src/lib/netlist/devices/nld_9316.cpp",
 		MAME_DIR .. "src/lib/netlist/devices/nld_9316.h",
+		MAME_DIR .. "src/lib/netlist/devices/nld_9322.cpp",
+		MAME_DIR .. "src/lib/netlist/devices/nld_9322.h",
+		MAME_DIR .. "src/lib/netlist/devices/nld_am2847.cpp",
+		MAME_DIR .. "src/lib/netlist/devices/nld_am2847.h",
+		MAME_DIR .. "src/lib/netlist/devices/nld_dm9334.cpp",
+		MAME_DIR .. "src/lib/netlist/devices/nld_dm9334.h",
 		MAME_DIR .. "src/lib/netlist/devices/nld_ne555.cpp",
 		MAME_DIR .. "src/lib/netlist/devices/nld_ne555.h",
 		MAME_DIR .. "src/lib/netlist/devices/nld_mm5837.cpp",
 		MAME_DIR .. "src/lib/netlist/devices/nld_mm5837.h",
 		MAME_DIR .. "src/lib/netlist/devices/nld_r2r_dac.cpp",
 		MAME_DIR .. "src/lib/netlist/devices/nld_r2r_dac.h",
+		MAME_DIR .. "src/lib/netlist/devices/nld_tristate.cpp",
+		MAME_DIR .. "src/lib/netlist/devices/nld_tristate.h",
 		MAME_DIR .. "src/lib/netlist/devices/nld_legacy.cpp",
 		MAME_DIR .. "src/lib/netlist/devices/nld_legacy.h",
 		MAME_DIR .. "src/lib/netlist/devices/net_lib.cpp",
diff --git a/scripts/src/sound.lua b/scripts/src/sound.lua
index fc55580..ab05c06 100644
--- a/scripts/src/sound.lua
+++ b/scripts/src/sound.lua
@@ -1401,3 +1401,26 @@ if (SOUNDS["VOLT_REG"]~=null) then
 		MAME_DIR .. "src/devices/sound/volt_reg.h",
 	}
 end
+
+---------------------------------------------------
+-- DAC-76 COMDAC
+-- at src/devices/sound/dac76.h,SOUNDS["DAC76"] = true
+---------------------------------------------------
+if (SOUNDS["DAC76"]~=null) then
+	files {
+		MAME_DIR .. "src/devices/sound/dac76.cpp",
+		MAME_DIR .. "src/devices/sound/dac76.h",
+	}
+end
+
+---------------------------------------------------
+-- MM5837 Noise Generator
+-- at src/devices/sound/mm5837.h,MACHINES["MM5837"] = true
+---------------------------------------------------
+
+if (SOUNDS["MM5837"]~=null) then
+	files {
+		MAME_DIR .. "src/devices/sound/mm5837.cpp",
+		MAME_DIR .. "src/devices/sound/mm5837.h",
+	}
+end
diff --git a/scripts/src/video.lua b/scripts/src/video.lua
index cad05c3..0bda850 100644
--- a/scripts/src/video.lua
+++ b/scripts/src/video.lua
@@ -900,3 +900,15 @@ if (VIDEOS["GBA_LCD"]~=null) then
 		MAME_DIR .. "src/devices/video/gba_lcd.h",
 	}
 end
+
+--------------------------------------------------
+--
+-- at src/devices/video/ef9369.h,VIDEOS["EF9369"] = true
+--------------------------------------------------
+
+if (VIDEOS["EF9369"]~=null) then
+	files {
+		MAME_DIR .. "src/devices/video/ef9369.cpp",
+		MAME_DIR .. "src/devices/video/ef9369.h",
+	}
+end
diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua
index 84fbe51..917e055 100644
--- a/scripts/target/mame/arcade.lua
+++ b/scripts/target/mame/arcade.lua
@@ -263,6 +263,8 @@ SOUNDS["AD1848"] = true
 --SOUNDS["UPD1771"] = true
 SOUNDS["VOLT_REG"] = true
 --SOUNDS["MEA8000"] = true
+SOUNDS["DAC76"] = true
+SOUNDS["MM5837"] = true
 
 --------------------------------------------------
 -- specify available video cores
@@ -283,6 +285,7 @@ VIDEOS["DM9368"] = true
 --VIDEOS["EF9345"] = true
 --VIDEOS["EF9364"] = true
 --VIDEOS["EF9365"] = true
+VIDEOS["EF9369"] = true
 --VIDEOS["GF4500"] = true
 VIDEOS["GF7600GS"] = true
 VIDEOS["EPIC12"] = true
@@ -359,6 +362,7 @@ MACHINES["TTL74123"] = true
 MACHINES["TTL74145"] = true
 MACHINES["TTL74148"] = true
 MACHINES["TTL74153"] = true
+MACHINES["TTL74157"] = true
 --MACHINES["TTL74161"] = true
 --MACHINES["TTL74175"] = true
 MACHINES["TTL74181"] = true
@@ -385,7 +389,7 @@ MACHINES["AY31015"] = true
 MACHINES["BANKDEV"] = true
 MACHINES["CDP1852"] = true
 MACHINES["CDP1871"] = true
---MACHINES["CMOS40105"] = true
+MACHINES["CMOS40105"] = true
 MACHINES["CDU76S"] = true
 MACHINES["COM8116"] = true
 MACHINES["CR589"] = true
@@ -563,6 +567,8 @@ MACHINES["X76F041"] = true
 MACHINES["X76F100"] = true
 MACHINES["Z80CTC"] = true
 MACHINES["Z80DART"] = true
+--MACHINES["Z80SIO"] = true
+MACHINES["Z80SCC"] = true
 MACHINES["Z80DMA"] = true
 MACHINES["Z80PIO"] = true
 MACHINES["Z80STI"] = true
@@ -1882,6 +1888,7 @@ files {
 	MAME_DIR .. "src/mame/machine/pgmprot_orlegend.cpp",
 	MAME_DIR .. "src/mame/machine/pgmprot_orlegend.h",
 	MAME_DIR .. "src/mame/drivers/pgm2.cpp",
+	MAME_DIR .. "src/mame/drivers/pgm3.cpp",
 	MAME_DIR .. "src/mame/drivers/spoker.cpp",
 	MAME_DIR .. "src/mame/machine/igs036crypt.cpp",
 	MAME_DIR .. "src/mame/machine/igs036crypt.h",
@@ -2483,10 +2490,6 @@ files {
 	MAME_DIR .. "src/mame/drivers/astrocde.cpp",
 	MAME_DIR .. "src/mame/includes/astrocde.h",
 	MAME_DIR .. "src/mame/video/astrocde.cpp",
-	MAME_DIR .. "src/mame/audio/gorf.cpp",
-	MAME_DIR .. "src/mame/audio/gorf.h",
-	MAME_DIR .. "src/mame/audio/wow.cpp",
-	MAME_DIR .. "src/mame/audio/wow.h",
 	MAME_DIR .. "src/mame/drivers/atlantis.cpp",
 	MAME_DIR .. "src/mame/drivers/balsente.cpp",
 	MAME_DIR .. "src/mame/includes/balsente.h",
@@ -2508,6 +2511,7 @@ files {
 	MAME_DIR .. "src/mame/includes/mcr68.h",
 	MAME_DIR .. "src/mame/machine/mcr68.cpp",
 	MAME_DIR .. "src/mame/video/mcr68.cpp",
+	MAME_DIR .. "src/mame/drivers/zwackery.cpp",
 	MAME_DIR .. "src/mame/drivers/midqslvr.cpp",
 	MAME_DIR .. "src/mame/drivers/midtunit.cpp",
 	MAME_DIR .. "src/mame/includes/midtunit.h",
@@ -2550,6 +2554,8 @@ files {
 	MAME_DIR .. "src/mame/machine/midwayic.h",
 	MAME_DIR .. "src/mame/audio/midway.cpp",
 	MAME_DIR .. "src/mame/audio/midway.h",
+	MAME_DIR .. "src/mame/audio/csd.cpp",
+	MAME_DIR .. "src/mame/audio/csd.h",
 }
 
 createMAMEProjects(_target, _subtarget, "namco")
@@ -2927,14 +2933,12 @@ files {
 	MAME_DIR .. "src/mame/drivers/pacman.cpp",
 	MAME_DIR .. "src/mame/includes/pacman.h",
 	MAME_DIR .. "src/mame/video/pacman.cpp",
-	MAME_DIR .. "src/mame/machine/acitya.cpp",
-	MAME_DIR .. "src/mame/machine/acitya.h",
+	MAME_DIR .. "src/mame/machine/epos.cpp",
+	MAME_DIR .. "src/mame/machine/epos.h",
 	MAME_DIR .. "src/mame/machine/jumpshot.cpp",
 	MAME_DIR .. "src/mame/machine/jumpshot.h",
 	MAME_DIR .. "src/mame/machine/pacplus.cpp",
 	MAME_DIR .. "src/mame/machine/pacplus.h",
-	MAME_DIR .. "src/mame/machine/theglobp.cpp",
-	MAME_DIR .. "src/mame/machine/theglobp.h",
 	MAME_DIR .. "src/mame/drivers/pengo.cpp",
 }
 
@@ -3044,8 +3048,8 @@ files {
 	MAME_DIR .. "src/mame/video/blockade.cpp",
 	MAME_DIR .. "src/mame/drivers/calorie.cpp",
 	MAME_DIR .. "src/mame/drivers/chihiro.cpp",
-	MAME_DIR .. "src/mame/includes/chihiro.h",
-	MAME_DIR .. "src/mame/video/chihiro.cpp",
+	MAME_DIR .. "src/mame/includes/xbox_nv2a.h",
+	MAME_DIR .. "src/mame/video/xbox_nv2a.cpp",
 	MAME_DIR .. "src/mame/drivers/coolridr.cpp",
 	MAME_DIR .. "src/mame/drivers/deniam.cpp",
 	MAME_DIR .. "src/mame/includes/deniam.h",
@@ -3966,10 +3970,6 @@ files {
 createMAMEProjects(_target, _subtarget, "tong")
 files {
 	MAME_DIR .. "src/mame/drivers/beezer.cpp",
-	MAME_DIR .. "src/mame/includes/beezer.h",
-	MAME_DIR .. "src/mame/machine/beezer.cpp",
-	MAME_DIR .. "src/mame/video/beezer.cpp",
-	MAME_DIR .. "src/mame/audio/beezer.cpp",
 }
 
 createMAMEProjects(_target, _subtarget, "unico")
@@ -4668,4 +4668,3 @@ files {
 	MAME_DIR .. "src/mame/video/xyonix.cpp",
 }
 end
-
diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua
index db74193..fe53f0b 100644
--- a/scripts/target/mame/mess.lua
+++ b/scripts/target/mame/mess.lua
@@ -264,6 +264,8 @@ SOUNDS["GB_SOUND"] = true
 SOUNDS["PCD3311"] = true
 SOUNDS["VOLT_REG"] = true
 SOUNDS["MEA8000"] = true
+--SOUNDS["DAC76"] = true
+--SOUNDS["MM5837"] = true
 
 --------------------------------------------------
 -- specify available video cores
@@ -284,6 +286,7 @@ VIDEOS["EF9340_1"] = true
 VIDEOS["EF9345"] = true
 VIDEOS["EF9364"] = true
 VIDEOS["EF9365"] = true
+--VIDEOS["EF9369"] = true
 VIDEOS["GF4500"] = true
 --VIDEOS+= EPIC12"] = true
 --VIDEOS+= FIXFREQ"] = true
@@ -375,6 +378,7 @@ MACHINES["AY31015"] = true
 MACHINES["BANKDEV"] = true
 MACHINES["CDP1852"] = true
 MACHINES["CDP1871"] = true
+MACHINES["CDP1879"] = true
 MACHINES["CMOS40105"] = true
 --MACHINES["CDU76S"] = true
 MACHINES["COM8116"] = true
@@ -534,6 +538,7 @@ MACHINES["TTL74123"] = true
 MACHINES["TTL74145"] = true
 MACHINES["TTL74148"] = true
 MACHINES["TTL74153"] = true
+--MACHINES["TTL74157"] = true
 MACHINES["TTL74161"] = true
 MACHINES["TTL74175"] = true
 MACHINES["TTL74181"] = true
@@ -900,6 +905,7 @@ function linkProjects_mame_mess(_target, _subtarget)
 		"dms",
 		"dragon",
 		"drc",
+		"dulmont",
 		"eaca",
 		"einis",
 		"elektor",
@@ -1135,8 +1141,6 @@ files {
 	MAME_DIR .. "src/mame/video/jagblit.h",
 	MAME_DIR .. "src/mame/video/jagblit.hxx",
 	MAME_DIR .. "src/mame/video/jagobj.hxx",
-	MAME_DIR .. "src/mame/audio/gorf.cpp",
-	MAME_DIR .. "src/mame/audio/wow.cpp",
 	MAME_DIR .. "src/mame/drivers/astrocde.cpp",
 	MAME_DIR .. "src/mame/includes/astrocde.h",
 	MAME_DIR .. "src/mame/video/astrocde.cpp",
@@ -1223,7 +1227,7 @@ files {
 	MAME_DIR .. "src/mame/drivers/cps1.cpp",
 	MAME_DIR .. "src/mame/includes/cps1.h",
 	MAME_DIR .. "src/mame/video/cps1.cpp",
-	MAME_DIR .. "src/mame/video/chihiro.cpp",
+	MAME_DIR .. "src/mame/video/xbox_nv2a.cpp",
 	MAME_DIR .. "src/mame/machine/xbox.cpp",
 	MAME_DIR .. "src/mame/machine/xbox_usb.cpp",
 	MAME_DIR .. "src/mame/includes/saturn.h",
@@ -1383,6 +1387,7 @@ files {
 	MAME_DIR .. "src/mame/drivers/lisa.cpp",
 	MAME_DIR .. "src/mame/includes/lisa.h",
 	MAME_DIR .. "src/mame/machine/lisa.cpp",
+	MAME_DIR .. "src/mame/drivers/lwriter.cpp",
 	MAME_DIR .. "src/mame/drivers/mac128.cpp",
 	MAME_DIR .. "src/mame/drivers/mac.cpp",
 	MAME_DIR .. "src/mame/includes/mac.h",
@@ -1763,6 +1768,11 @@ files {
 	MAME_DIR .. "src/mame/drivers/zrt80.cpp",
 }
 
+createMESSProjects(_target, _subtarget, "dulmont")
+files {
+	MAME_DIR .. "src/mame/drivers/magnum.cpp",
+}
+
 createMESSProjects(_target, _subtarget, "eaca")
 files {
 	MAME_DIR .. "src/mame/drivers/cgenie.cpp",
@@ -1883,6 +1893,7 @@ files {
 
 createMESSProjects(_target, _subtarget, "force")
 files {
+	MAME_DIR .. "src/mame/drivers/fccpu20.cpp",
 	MAME_DIR .. "src/mame/drivers/fccpu30.cpp",
 	MAME_DIR .. "src/mame/drivers/force68k.cpp",
 }
@@ -2431,6 +2442,7 @@ files {
 	MAME_DIR .. "src/mame/drivers/pc.cpp",
 	MAME_DIR .. "src/mame/drivers/pcipc.cpp",
 	MAME_DIR .. "src/mame/drivers/tandy1t.cpp",
+	MAME_DIR .. "src/mame/drivers/tosh1000.cpp",
 	MAME_DIR .. "src/mame/video/pc_t1t.cpp",
 	MAME_DIR .. "src/mame/video/pc_t1t.h",
 }
@@ -3329,6 +3341,8 @@ files {
 	MAME_DIR .. "src/mame/drivers/mx2178.cpp",
 	MAME_DIR .. "src/mame/drivers/mycom.cpp",
 	MAME_DIR .. "src/mame/drivers/myvision.cpp",
+	MAME_DIR .. "src/mame/machine/nl_hazelvid.cpp",
+	MAME_DIR .. "src/mame/machine/nl_hazelvid.h",
 	MAME_DIR .. "src/mame/drivers/notetaker.cpp",
 	MAME_DIR .. "src/mame/drivers/ngen.cpp",
 	MAME_DIR .. "src/mame/machine/ngen_kb.cpp",
diff --git a/scripts/target/mame/nl.lua b/scripts/target/mame/nl.lua
index 8242f67..2a02ab3 100644
--- a/scripts/target/mame/nl.lua
+++ b/scripts/target/mame/nl.lua
@@ -21,6 +21,7 @@ CPUS["M6800"] = true
 CPUS["M6803"] = true
 CPUS["M6809"] = true
 CPUS["MCS48"] = true
+CPUS["I8085"] = true
 --CPUS["MCS51"] = true
 --CPUS["M6800"] = true
 --CPUS["M6809"] = true
@@ -60,6 +61,10 @@ VIDEOS["FIXFREQ"] = true
 MACHINES["NETLIST"] = true
 MACHINES["Z80DMA"] = true
 MACHINES["GEN_LATCH"] = true
+MACHINES["AY31015"] = true
+MACHINES["KB3600"] = true
+MACHINES["COM8116"] = true
+
 --MACHINES["6821PIA"] = true
 --MACHINES["TTL74148"] = true
 --MACHINES["TTL74153"] = true
@@ -112,6 +117,12 @@ files{
 	MAME_DIR .. "src/mame/machine/nl_pongd.h",
 	MAME_DIR .. "src/mame/machine/nl_breakout.cpp",
 	MAME_DIR .. "src/mame/machine/nl_breakout.h",
+	MAME_DIR .. "src/mame/machine/nl_hazelvid.cpp",
+	MAME_DIR .. "src/mame/machine/nl_hazelvid.h",
+
+	MAME_DIR .. "src/mame/drivers/atarittl.cpp",
+
+  MAME_DIR .. "src/mame/drivers/hazeltin.cpp",
 
 	MAME_DIR .. "src/mame/drivers/1942.cpp",
 	MAME_DIR .. "src/mame/includes/1942.h",
@@ -133,6 +144,7 @@ files{
 	MAME_DIR .. "src/mame/audio/irem.h",
 	MAME_DIR .. "src/mame/audio/nl_kidniki.cpp",
 	MAME_DIR .. "src/mame/audio/nl_kidniki.h",
+
 }
 end
 
diff --git a/scripts/target/mame/tiny.lua b/scripts/target/mame/tiny.lua
index 0e77093..129e276 100644
--- a/scripts/target/mame/tiny.lua
+++ b/scripts/target/mame/tiny.lua
@@ -139,8 +139,6 @@ files{
 	MAME_DIR .. "src/mame/audio/williams.cpp",
 	MAME_DIR .. "src/mame/audio/williams.h",
 	MAME_DIR .. "src/mame/video/williams.cpp",
-	MAME_DIR .. "src/mame/audio/gorf.cpp",
-	MAME_DIR .. "src/mame/audio/wow.cpp",
 	MAME_DIR .. "src/mame/drivers/gaelco.cpp",
 	MAME_DIR .. "src/mame/includes/gaelco.h",
 	MAME_DIR .. "src/mame/video/gaelco.cpp",
diff --git a/src/devices/bus/a2bus/a2midi.cpp b/src/devices/bus/a2bus/a2midi.cpp
index b726256..ab72508 100644
--- a/src/devices/bus/a2bus/a2midi.cpp
+++ b/src/devices/bus/a2bus/a2midi.cpp
@@ -27,8 +27,7 @@ const device_type A2BUS_MIDI = &device_creator<a2bus_midi_device>;
 #define MIDI_ACIA_TAG    "midi_acia"
 
 MACHINE_CONFIG_FRAGMENT( midi )
-	MCFG_DEVICE_ADD(MIDI_PTM_TAG, PTM6840, 0)
-	MCFG_PTM6840_INTERNAL_CLOCK(1021800.0f)
+	MCFG_DEVICE_ADD(MIDI_PTM_TAG, PTM6840, 1021800)
 	MCFG_PTM6840_EXTERNAL_CLOCKS(1021800.0f, 1021800.0f, 1021800.0f)
 	MCFG_PTM6840_IRQ_CB(WRITELINE(a2bus_midi_device, ptm_irq_w))
 
diff --git a/src/devices/bus/a7800/a78_carts.h b/src/devices/bus/a7800/a78_carts.h
index ebf66de..e098f10 100644
--- a/src/devices/bus/a7800/a78_carts.h
+++ b/src/devices/bus/a7800/a78_carts.h
@@ -17,6 +17,7 @@ static SLOT_INTERFACE_START(a7800_cart)
 	SLOT_INTERFACE_INTERNAL("a78_sg_pokey", A78_ROM_SG_POKEY)
 	SLOT_INTERFACE_INTERNAL("a78_sg_ram",   A78_ROM_SG_RAM)
 	SLOT_INTERFACE_INTERNAL("a78_sg9",      A78_ROM_SG9)
+	SLOT_INTERFACE_INTERNAL("a78_mram",     A78_ROM_MRAM)
 	SLOT_INTERFACE_INTERNAL("a78_abs",      A78_ROM_ABSOLUTE)
 	SLOT_INTERFACE_INTERNAL("a78_act",      A78_ROM_ACTIVISION)
 	SLOT_INTERFACE_INTERNAL("a78_hsc",      A78_HISCORE)
diff --git a/src/devices/bus/a7800/a78_slot.cpp b/src/devices/bus/a7800/a78_slot.cpp
index a68e0da..a9208c9 100644
--- a/src/devices/bus/a7800/a78_slot.cpp
+++ b/src/devices/bus/a7800/a78_slot.cpp
@@ -306,6 +306,7 @@ static const a78_slot slot_list[] =
 	{ A78_TYPE3,      "a78_sg_pokey" },
 	{ A78_TYPE6,      "a78_sg_ram" },
 	{ A78_TYPEA,      "a78_sg9" },
+	{ A78_TYPE8,      "a78_mram" },
 	{ A78_ABSOLUTE,   "a78_abs" },
 	{ A78_ACTIVISION, "a78_act" },
 	{ A78_HSC,        "a78_hsc" },
@@ -429,6 +430,10 @@ image_init_result a78_cart_slot_device::call_load()
 				m_type = A78_ACTIVISION;
 			else if ((mapper & 0xff00) == 0x0200)
 				m_type = A78_ABSOLUTE;
+			// (for now) mirror ram implies no bankswitch format is used
+			else if ((mapper & 0x0080) == 0x0080)
+				m_type = A78_TYPE8;
+
 
 			logerror("Cart type: 0x%x\n", m_type);
 
@@ -454,7 +459,7 @@ image_init_result a78_cart_slot_device::call_load()
 			m_cart->rom_alloc(len, tag());
 			fread(m_cart->get_rom_base(), len);
 
-			if (m_type == A78_TYPE6)
+			if (m_type == A78_TYPE6 || m_type == A78_TYPE8)
 				m_cart->ram_alloc(0x4000);
 			if (m_type == A78_MEGACART || (m_type >= A78_VERSABOARD && m_type <= A78_VERSA_POK450))
 				m_cart->ram_alloc(0x8000);
@@ -570,6 +575,8 @@ std::string a78_cart_slot_device::get_default_card_software()
 			type = A78_ACTIVISION;
 		else if ((mapper & 0xff00) == 0x0200)
 			type = A78_ABSOLUTE;
+		else if ((mapper & 0x0080) == 0x0080)
+			type = A78_TYPE8;
 
 		logerror("Cart type: %x\n", type);
 		slot_string = a78_get_slot(type);
@@ -706,7 +713,7 @@ WRITE8_MEMBER(a78_cart_slot_device::write_40xx)
  bit 4 [0x10] - bank 6 at $4000
  bit 5 [0x20] - banked RAM at $4000
  bit 6 [0x40] - POKEY at $0450
- bit 7 [0x80] - currently unused
+ bit 7 [0x80] - Mirror RAM at $4000
 
  (byte 53)
  bit0 set = Absolute mapper (F18 Hornet)
@@ -751,6 +758,9 @@ void a78_cart_slot_device::internal_header_logging(uint8_t *header, uint32_t len
 		case 0x0020:
 			cart_mapper.assign("SuperCart Bankswitch + 32K RAM");
 			break;
+		case 0x0080:
+			cart_mapper.assign("No Bankswitch + Mirror RAM");
+			break;
 		case 0x0100:
 			cart_mapper.assign("Activision Bankswitch");
 			break;
@@ -809,6 +819,7 @@ void a78_cart_slot_device::internal_header_logging(uint8_t *header, uint32_t len
 	logerror( "\t\tbank6 at $4000:  %s\n", BIT(head_mapper, 4) ? "Yes" : "No");
 	logerror( "\t\tbanked RAM:      %s\n", BIT(head_mapper, 5) ? "Yes" : "No");
 	logerror( "\t\tPOKEY at $450:   %s\n", BIT(head_mapper, 6) ? "Yes" : "No");
+	logerror( "\t\tmRAM at $4000:   %s\n", BIT(head_mapper, 7) ? "Yes" : "No");
 	logerror( "\t\tSpecial:         %s ", (head_mapper & 0xff00) ? "Yes" : "No");
 	if (head_mapper & 0xff00)
 	{
diff --git a/src/devices/bus/a7800/a78_slot.h b/src/devices/bus/a7800/a78_slot.h
index bb9f964..6b63b8c 100644
--- a/src/devices/bus/a7800/a78_slot.h
+++ b/src/devices/bus/a7800/a78_slot.h
@@ -19,7 +19,8 @@ enum
 	A78_TYPE2,          // Atari SuperGame pcb (8x16K banks with bankswitch)
 	A78_TYPE3,          // as TYPE1 + POKEY chip on the PCB
 	A78_TYPE6,          // as TYPE1 + RAM IC on the PCB
-	A78_TYPEA,          // Alien Brigade, Crossbow (9x16K banks with diff bankswitch)
+	A78_TYPE8,          // Rescue on Fractalus, as TYPE0 + 2K Mirror RAM IC on the PCB
+ 	A78_TYPEA,          // Alien Brigade, Crossbow (9x16K banks with diff bankswitch)
 	A78_ABSOLUTE,       // F18 Hornet
 	A78_ACTIVISION,     // Double Dragon, Rampage
 	A78_HSC,            // Atari HighScore cart
diff --git a/src/devices/bus/a7800/rom.cpp b/src/devices/bus/a7800/rom.cpp
index 3b230e7..b55445a 100644
--- a/src/devices/bus/a7800/rom.cpp
+++ b/src/devices/bus/a7800/rom.cpp
@@ -32,6 +32,7 @@ const device_type A78_ROM_POKEY = &device_creator<a78_rom_pokey_device>;
 const device_type A78_ROM_SG_POKEY = &device_creator<a78_rom_sg_pokey_device>;
 const device_type A78_ROM_SG_RAM = &device_creator<a78_rom_sg_ram_device>;
 const device_type A78_ROM_SG9 = &device_creator<a78_rom_sg9_device>;
+const device_type A78_ROM_MRAM = &device_creator<a78_rom_mram_device>;
 const device_type A78_ROM_ABSOLUTE = &device_creator<a78_rom_abs_device>;
 const device_type A78_ROM_ACTIVISION = &device_creator<a78_rom_act_device>;
 
@@ -67,6 +68,16 @@ a78_rom_pokey_device::a78_rom_pokey_device(const machine_config &mconfig, const
 }
 
 
+a78_rom_mram_device::a78_rom_mram_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, uint32_t clock, const char *shortname, const char *source)
+					: a78_rom_device(mconfig, type, name, tag, owner, clock, shortname, source)
+{
+}
+
+a78_rom_mram_device::a78_rom_mram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+					: a78_rom_device(mconfig, A78_ROM_MRAM, "Atari 7800 ROM Carts + Mirror RAM", tag, owner, clock, "a78_rom_mram", __FILE__)
+{
+}
+
 a78_rom_sg_device::a78_rom_sg_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, uint32_t clock, const char *shortname, const char *source)
 					: a78_rom_device(mconfig, type, name, tag, owner, clock, shortname, source), m_bank(0)
 				{
@@ -261,6 +272,35 @@ machine_config_constructor a78_rom_pokey_device::device_mconfig_additions() cons
 	return MACHINE_CONFIG_NAME( a78_pokey );
 }
 
+/*-------------------------------------------------
+
+ Carts with no bankswitch + mRAM chip
+ The RAM chips are accessed by writing at
+ 0x4000-0x7fff.
+ The A8 line of the RAM chip isn't used, to create
+ mirrors of even pages at odd page locations.
+
+ GAMES: Rescue on Fractalus (proto)
+
+ -------------------------------------------------*/
+
+
+READ8_MEMBER(a78_rom_mram_device::read_40xx)
+{
+	if (offset < 0x4000)
+		return m_ram[offset & 0xfeff];
+	if (offset + 0x4000 < m_base_rom)
+		return 0xff;
+	else
+		return m_rom[offset + 0x4000 - m_base_rom];
+}
+
+WRITE8_MEMBER(a78_rom_mram_device::write_40xx)
+{
+	if (offset < 0x4000)
+		m_ram[offset&0xfeff] = data;
+}
+
 
 /*-------------------------------------------------
 
diff --git a/src/devices/bus/a7800/rom.h b/src/devices/bus/a7800/rom.h
index 3e64f65..5036b53 100644
--- a/src/devices/bus/a7800/rom.h
+++ b/src/devices/bus/a7800/rom.h
@@ -47,6 +47,21 @@ protected:
 };
 
 
+// ======================> a78_rom_sg_ram_device
+
+class a78_rom_mram_device : public a78_rom_device
+{
+public:
+	// construction/destruction
+	a78_rom_mram_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, uint32_t clock, const char *shortname, const char *source);
+	a78_rom_mram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+	// reading and writing
+	virtual DECLARE_READ8_MEMBER(read_40xx) override;
+	virtual DECLARE_WRITE8_MEMBER(write_40xx) override;
+};
+
+
 // ======================> a78_rom_sg_device
 
 class a78_rom_sg_device : public a78_rom_device
@@ -248,6 +263,7 @@ extern const device_type A78_ROM_SG;
 extern const device_type A78_ROM_POKEY;
 extern const device_type A78_ROM_SG_POKEY;
 extern const device_type A78_ROM_SG_RAM;
+extern const device_type A78_ROM_MRAM;
 extern const device_type A78_ROM_SG9;
 extern const device_type A78_ROM_ABSOLUTE;
 extern const device_type A78_ROM_ACTIVISION;
diff --git a/src/devices/bus/amiga/zorro/buddha.cpp b/src/devices/bus/amiga/zorro/buddha.cpp
index 98a15a1..bbfe7ad 100644
--- a/src/devices/bus/amiga/zorro/buddha.cpp
+++ b/src/devices/bus/amiga/zorro/buddha.cpp
@@ -6,6 +6,20 @@
 
     Zorro-II IDE controller
 
+    The 'speed' register is used to select the IDE timing according to
+    the following table (bits 7-5 are used):
+
+    0    497ns   7c  to select, IOR/IOW after 172ns  2c
+    1    639ns   9c  to select, IOR/IOW after 243ns  3c
+    2    781ns  11c  to select, IOR/IOW after 314ns  4c
+    3    355ns   5c  to select, IOR/IOW after 101ns  1c
+    4    355ns   5c  to select, IOR/IOW after 172ns  2c
+    5    355ns   5c  to select, IOR/IOW after 243ns  3c
+    6   1065ns  15c  to select, IOR/IOW after 314ns  4c
+    7    355ns   5c  to select, IOR/IOW after 101ns  1c
+
+    c = clock cycles. This isn't emulated.
+
 ***************************************************************************/
 
 #include "buddha.h"
@@ -24,6 +38,21 @@
 const device_type BUDDHA = &device_creator<buddha_device>;
 
 //-------------------------------------------------
+//  mmio_map - device-specific memory mapped I/O
+//-------------------------------------------------
+
+DEVICE_ADDRESS_MAP_START( mmio_map, 16, buddha_device )
+	AM_RANGE(0x7fe, 0x7ff) AM_READWRITE(speed_r, speed_w)
+	AM_RANGE(0x800, 0x8ff) AM_READWRITE(ide_0_cs0_r, ide_0_cs0_w)
+	AM_RANGE(0x900, 0x9ff) AM_READWRITE(ide_0_cs1_r, ide_0_cs1_w)
+	AM_RANGE(0xa00, 0xaff) AM_READWRITE(ide_1_cs0_r, ide_1_cs0_w)
+	AM_RANGE(0xb00, 0xbff) AM_READWRITE(ide_1_cs1_r, ide_1_cs1_w)
+	AM_RANGE(0xf00, 0xf3f) AM_READ(ide_0_interrupt_r)
+	AM_RANGE(0xf40, 0xf7f) AM_READ(ide_1_interrupt_r)
+	AM_RANGE(0xfc0, 0xfff) AM_WRITE(ide_interrupt_enable_w)
+ADDRESS_MAP_END
+
+//-------------------------------------------------
 //  machine_config_additions - device-specific
 //  machine configurations
 //-------------------------------------------------
@@ -45,10 +74,10 @@ machine_config_constructor buddha_device::device_mconfig_additions() const
 //-------------------------------------------------
 
 ROM_START( buddha )
-	ROM_REGION16_BE(0x10000, "bootrom", 0)
+	ROM_REGION16_BE(0x10000, "bootrom", ROMREGION_ERASEFF)
 	ROM_DEFAULT_BIOS("v103-17")
 	ROM_SYSTEM_BIOS(0, "v103-8", "Version 103.8")
-	ROMX_LOAD("buddha_103-8.rom", 0x0000, 0x8000, CRC(44f81426) SHA1(95555c6690b5c697e1cdca2726e47c1c6c194d7c), ROM_SKIP(1) | ROM_BIOS(1))
+	ROMX_LOAD("buddha_103-8.rom",  0x0000, 0x8000, CRC(44f81426) SHA1(95555c6690b5c697e1cdca2726e47c1c6c194d7c), ROM_SKIP(1) | ROM_BIOS(1))
 	ROM_SYSTEM_BIOS(1, "v103-17", "Version 103.17")
 	ROMX_LOAD("buddha_103-17.rom", 0x0000, 0x8000, CRC(2b7b24e0) SHA1(ec17a58962c373a2892090ec9b1722d2c326d631), ROM_SKIP(1) | ROM_BIOS(2))
 ROM_END
@@ -85,6 +114,10 @@ buddha_device::buddha_device(const machine_config &mconfig, const char *tag, dev
 void buddha_device::device_start()
 {
 	set_zorro_device();
+
+	save_item(NAME(m_ide_interrupts_enabled));
+	save_item(NAME(m_ide_0_interrupt));
+	save_item(NAME(m_ide_1_interrupt));
 }
 
 //-------------------------------------------------
@@ -93,6 +126,9 @@ void buddha_device::device_start()
 
 void buddha_device::device_reset()
 {
+	m_ide_interrupts_enabled = false;
+	m_ide_0_interrupt = 0;
+	m_ide_1_interrupt = 0;
 }
 
 
@@ -103,7 +139,7 @@ void buddha_device::device_reset()
 void buddha_device::autoconfig_base_address(offs_t address)
 {
 	if (VERBOSE)
-		logerror("%s('%s'): autoconfig_base_address received: 0x%06x\n", shortname(), basetag(), address);
+		logerror("autoconfig_base_address received: 0x%06x\n", address);
 
 	if (VERBOSE)
 		logerror("-> installing buddha\n");
@@ -111,41 +147,14 @@ void buddha_device::autoconfig_base_address(offs_t address)
 	// stop responding to default autoconfig
 	m_slot->m_space->unmap_readwrite(0xe80000, 0xe8007f);
 
+	// buddha registers
+	m_slot->m_space->install_device(address, address + 0xfff, *this, &buddha_device::mmio_map);
+
 	// install autoconfig handler to new location
 	m_slot->m_space->install_readwrite_handler(address, address + 0x7f,
 		read16_delegate(FUNC(amiga_autoconfig::autoconfig_read), static_cast<amiga_autoconfig *>(this)),
 		write16_delegate(FUNC(amiga_autoconfig::autoconfig_write), static_cast<amiga_autoconfig *>(this)), 0xffff);
 
-	// buddha registers
-	m_slot->m_space->install_readwrite_handler(address + 0x7fe, address + 0x7ff,
-		read16_delegate(FUNC(buddha_device::speed_r), this),
-		write16_delegate(FUNC(buddha_device::speed_w), this), 0xffff);
-
-	m_slot->m_space->install_readwrite_handler(address + 0x800, address + 0x8ff,
-		read16_delegate(FUNC(buddha_device::ide_0_cs0_r), this),
-		write16_delegate(FUNC(buddha_device::ide_0_cs0_w), this), 0xffff);
-
-	m_slot->m_space->install_readwrite_handler(address + 0x900, address + 0x9ff,
-		read16_delegate(FUNC(buddha_device::ide_0_cs1_r), this),
-		write16_delegate(FUNC(buddha_device::ide_0_cs1_w), this), 0xffff);
-
-	m_slot->m_space->install_readwrite_handler(address + 0xa00, address + 0xaff,
-		read16_delegate(FUNC(buddha_device::ide_0_cs0_r), this),
-		write16_delegate(FUNC(buddha_device::ide_0_cs0_w), this), 0xffff);
-
-	m_slot->m_space->install_readwrite_handler(address + 0xb00, address + 0xbff,
-		read16_delegate(FUNC(buddha_device::ide_0_cs1_r), this),
-		write16_delegate(FUNC(buddha_device::ide_0_cs1_w), this), 0xffff);
-
-	m_slot->m_space->install_read_handler(address + 0xf00, address + 0xf3f,
-		read16_delegate(FUNC(buddha_device::ide_0_interrupt_r), this), 0xffff);
-
-	m_slot->m_space->install_read_handler(address + 0xf40, address + 0xf7f,
-		read16_delegate(FUNC(buddha_device::ide_1_interrupt_r), this), 0xffff);
-
-	m_slot->m_space->install_write_handler(address + 0xfc0, address + 0xfff,
-		write16_delegate(FUNC(buddha_device::ide_interrupt_enable_w), this), 0xffff);
-
 	// install access to the rom space
 	m_slot->m_space->install_rom(address + 0x1000, address + 0xffff, memregion("bootrom")->base() + 0x1000);
 
@@ -156,7 +165,7 @@ void buddha_device::autoconfig_base_address(offs_t address)
 WRITE_LINE_MEMBER( buddha_device::cfgin_w )
 {
 	if (VERBOSE)
-		logerror("%s('%s'): configin_w (%d)\n", shortname(), basetag(), state);
+		logerror("configin_w (%d)\n", state);
 
 	if (state == 0)
 	{
@@ -185,7 +194,7 @@ READ16_MEMBER( buddha_device::speed_r )
 	uint16_t data = 0xffff;
 
 	if (VERBOSE)
-		logerror("%s('%s'): ide_0_interrupt_r %04x [mask = %04x]\n", shortname(), basetag(), data, mem_mask);
+		logerror("speed_r %04x [mask = %04x]\n", data, mem_mask);
 
 	return data;
 }
@@ -193,13 +202,13 @@ READ16_MEMBER( buddha_device::speed_r )
 WRITE16_MEMBER( buddha_device::speed_w )
 {
 	if (VERBOSE)
-		logerror("%s('%s'): speed_w %04x [mask = %04x]\n", shortname(), basetag(), data, mem_mask);
+		logerror("speed_w %04x [mask = %04x]\n", data, mem_mask);
 }
 
 WRITE_LINE_MEMBER( buddha_device::ide_0_interrupt_w)
 {
 	if (VERBOSE)
-		logerror("%s('%s'): ide_0_interrupt_w (%d)\n", shortname(), basetag(), state);
+		logerror("ide_0_interrupt_w (%d)\n", state);
 
 	m_ide_0_interrupt = state;
 
@@ -210,7 +219,7 @@ WRITE_LINE_MEMBER( buddha_device::ide_0_interrupt_w)
 WRITE_LINE_MEMBER( buddha_device::ide_1_interrupt_w)
 {
 	if (VERBOSE)
-		logerror("%s('%s'): ide_1_interrupt_w (%d)\n", shortname(), basetag(), state);
+		logerror("ide_1_interrupt_w (%d)\n", state);
 
 	m_ide_1_interrupt = state;
 
@@ -224,10 +233,8 @@ READ16_MEMBER( buddha_device::ide_0_interrupt_r )
 
 	data = m_ide_0_interrupt << 15;
 
-	if (VERBOSE)
-		logerror("%s('%s'): ide_0_interrupt_r %04x [mask = %04x]\n", shortname(), basetag(), data, mem_mask);
-
-	logerror("%s\n", device().machine().describe_context());
+	if (VERBOSE && 0)
+		logerror("ide_0_interrupt_r %04x [mask = %04x]\n", data, mem_mask);
 
 	return data;
 }
@@ -238,8 +245,8 @@ READ16_MEMBER( buddha_device::ide_1_interrupt_r )
 
 	data = m_ide_1_interrupt << 15;
 
-	if (VERBOSE)
-		logerror("%s('%s'): ide_1_interrupt_r %04x [mask = %04x]\n", shortname(), basetag(), data, mem_mask);
+	if (VERBOSE && 0)
+		logerror("ide_1_interrupt_r %04x [mask = %04x]\n", data, mem_mask);
 
 	return data;
 }
@@ -247,7 +254,7 @@ READ16_MEMBER( buddha_device::ide_1_interrupt_r )
 WRITE16_MEMBER( buddha_device::ide_interrupt_enable_w )
 {
 	if (VERBOSE)
-		logerror("%s('%s'): ide_interrupt_enable_w %04x [mask = %04x]\n", shortname(), basetag(), data, mem_mask);
+		logerror("ide_interrupt_enable_w %04x [mask = %04x]\n", data, mem_mask);
 
 	// writing any value here enables ide interrupts to the zorro slot
 	m_ide_interrupts_enabled = true;
@@ -255,21 +262,19 @@ WRITE16_MEMBER( buddha_device::ide_interrupt_enable_w )
 
 READ16_MEMBER( buddha_device::ide_0_cs0_r )
 {
-	uint16_t data;
-
-	mem_mask = (mem_mask << 8) | (mem_mask >> 8);
-	data = m_ata_0->read_cs0(space, (offset >> 1) & 0x07, mem_mask);
+	uint16_t data = m_ata_0->read_cs0(space, (offset >> 1) & 0x07, (mem_mask << 8) | (mem_mask >> 8));
+	data = (data << 8) | (data >> 8);
 
 	if (VERBOSE)
-		logerror("%s('%s'): ide_0_cs0_r(%04x) %04x [mask = %04x]\n", shortname(), basetag(), offset, data, mem_mask);
+		logerror("ide_0_cs0_r(%04x) %04x [mask = %04x]\n", offset, data, mem_mask);
 
-	return (data << 8) | (data >> 8);
+	return data;
 }
 
 WRITE16_MEMBER( buddha_device::ide_0_cs0_w )
 {
 	if (VERBOSE)
-		logerror("%s('%s'): ide_0_cs0_w(%04x) %04x [mask = %04x]\n", shortname(), basetag(), offset, data, mem_mask);
+		logerror("ide_0_cs0_w(%04x) %04x [mask = %04x]\n", offset, data, mem_mask);
 
 	mem_mask = (mem_mask << 8) | (mem_mask >> 8);
 	data = (data << 8) | (data >> 8);
@@ -279,21 +284,19 @@ WRITE16_MEMBER( buddha_device::ide_0_cs0_w )
 
 READ16_MEMBER( buddha_device::ide_0_cs1_r )
 {
-	uint16_t data;
-
-	mem_mask = (mem_mask << 8) | (mem_mask >> 8);
-	data = m_ata_0->read_cs1(space, (offset >> 1) & 0x07, mem_mask);
+	uint16_t data = m_ata_0->read_cs1(space, (offset >> 1) & 0x07, (mem_mask << 8) | (mem_mask >> 8));
+	data = (data << 8) | (data >> 8);
 
 	if (VERBOSE)
-		logerror("%s('%s'): ide_0_cs1_r(%04x) %04x [mask = %04x]\n", shortname(), basetag(), offset, data, mem_mask);
+		logerror("ide_0_cs1_r(%04x) %04x [mask = %04x]\n", offset, data, mem_mask);
 
-	return (data << 8) | (data >> 8);
+	return data;
 }
 
 WRITE16_MEMBER( buddha_device::ide_0_cs1_w )
 {
 	if (VERBOSE)
-		logerror("%s('%s'): ide_0_cs1_w(%04x) %04x [mask = %04x]\n", shortname(), basetag(), offset, data, mem_mask);
+		logerror("ide_0_cs1_w(%04x) %04x [mask = %04x]\n", offset, data, mem_mask);
 
 	mem_mask = (mem_mask << 8) | (mem_mask >> 8);
 	data = (data << 8) | (data >> 8);
@@ -303,21 +306,19 @@ WRITE16_MEMBER( buddha_device::ide_0_cs1_w )
 
 READ16_MEMBER( buddha_device::ide_1_cs0_r )
 {
-	uint16_t data;
-
-	mem_mask = (mem_mask << 8) | (mem_mask >> 8);
-	data = m_ata_1->read_cs0(space, (offset >> 1) & 0x07, mem_mask);
+	uint16_t data = m_ata_1->read_cs0(space, (offset >> 1) & 0x07, (mem_mask << 8) | (mem_mask >> 8));
+	data = (data << 8) | (data >> 8);
 
 	if (VERBOSE)
-		logerror("%s('%s'): ide_1_cs0_r(%04x) %04x [mask = %04x]\n", shortname(), basetag(), offset, data, mem_mask);
+		logerror("ide_1_cs0_r(%04x) %04x [mask = %04x]\n", offset, data, mem_mask);
 
-	return (data << 8) | (data >> 8);
+	return data;
 }
 
 WRITE16_MEMBER( buddha_device::ide_1_cs0_w )
 {
 	if (VERBOSE)
-		logerror("%s('%s'): ide_1_cs0_w(%04x) %04x [mask = %04x]\n", shortname(), basetag(), offset, data, mem_mask);
+		logerror("ide_1_cs0_w(%04x) %04x [mask = %04x]\n", offset, data, mem_mask);
 
 	mem_mask = (mem_mask << 8) | (mem_mask >> 8);
 	data = (data << 8) | (data >> 8);
@@ -327,21 +328,19 @@ WRITE16_MEMBER( buddha_device::ide_1_cs0_w )
 
 READ16_MEMBER( buddha_device::ide_1_cs1_r )
 {
-	uint16_t data;
-
-	mem_mask = (mem_mask << 8) | (mem_mask >> 8);
-	data = m_ata_1->read_cs1(space, (offset >> 1) & 0x07, mem_mask);
+	uint16_t data = m_ata_1->read_cs1(space, (offset >> 1) & 0x07, (mem_mask << 8) | (mem_mask >> 8));
+	data = (data << 8) | (data >> 8);
 
 	if (VERBOSE)
-		logerror("%s('%s'): ide_1_cs1_r(%04x) %04x [mask = %04x]\n", shortname(), basetag(), offset, data, mem_mask);
+		logerror("ide_1_cs1_r(%04x) %04x [mask = %04x]\n", offset, data, mem_mask);
 
-	return (data << 8) | (data >> 8);
+	return data;
 }
 
 WRITE16_MEMBER( buddha_device::ide_1_cs1_w )
 {
 	if (VERBOSE)
-		logerror("%s('%s'): ide_1_cs1_w(%04x) %04x [mask = %04x]\n", shortname(), basetag(), offset, data, mem_mask);
+		logerror("ide_1_cs1_w(%04x) %04x [mask = %04x]\n", offset, data, mem_mask);
 
 	mem_mask = (mem_mask << 8) | (mem_mask >> 8);
 	data = (data << 8) | (data >> 8);
diff --git a/src/devices/bus/amiga/zorro/buddha.h b/src/devices/bus/amiga/zorro/buddha.h
index 712cf69..14b6d1b 100644
--- a/src/devices/bus/amiga/zorro/buddha.h
+++ b/src/devices/bus/amiga/zorro/buddha.h
@@ -31,6 +31,8 @@ public:
 	// construction/destruction
 	buddha_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
 
+	DECLARE_ADDRESS_MAP(mmio_map, 16);
+
 	// speed register
 	DECLARE_READ16_MEMBER( speed_r );
 	DECLARE_WRITE16_MEMBER( speed_w );
diff --git a/src/devices/bus/apricot/keyboard/hle.cpp b/src/devices/bus/apricot/keyboard/hle.cpp
index d0f4eaa..ff2f9ff 100644
--- a/src/devices/bus/apricot/keyboard/hle.cpp
+++ b/src/devices/bus/apricot/keyboard/hle.cpp
@@ -4,6 +4,11 @@
 
     ACT Apricot Keyboard (HLE)
 
+    TODO:
+    - MicroScreen emulation
+    - Mouse emulation
+    - LEDs
+
     Keyboard to System:
     - 01-60: Key make codes
     - 70-7f: Mouse codes
@@ -308,6 +313,11 @@ void apricot_keyboard_hle_device::received_byte(uint8_t byte)
 
 			break;
 
+		case CMD_KEYBOARD_RESET:
+			logerror("System requests keyboard reset\n");
+			transmit_byte(ACK_DIAGNOSTICS);
+			break;
+
 		default:
 			logerror("Unhandled command: %02x\n", byte);
 		}
diff --git a/src/devices/bus/apricot/keyboard/hle.h b/src/devices/bus/apricot/keyboard/hle.h
index e1cef56..cc8369d 100644
--- a/src/devices/bus/apricot/keyboard/hle.h
+++ b/src/devices/bus/apricot/keyboard/hle.h
@@ -57,7 +57,12 @@ private:
 
 	enum {
 		CMD_REQ_TIME_AND_DATE = 0xe1,
-		CMD_SET_TIME_AND_DATE = 0xe4
+		CMD_SET_TIME_AND_DATE = 0xe4,
+		CMD_KEYBOARD_RESET    = 0xe8
+	};
+
+	enum {
+		ACK_DIAGNOSTICS = 0xfb
 	};
 
 	int m_rtc_index;
diff --git a/src/devices/bus/c64/magic_voice.cpp b/src/devices/bus/c64/magic_voice.cpp
index 078ca95..a3a8353 100644
--- a/src/devices/bus/c64/magic_voice.cpp
+++ b/src/devices/bus/c64/magic_voice.cpp
@@ -49,7 +49,7 @@ http://www.stefan-uhlmann.de/cbm/MVM/index.html
 
 #define T6721A_TAG      "u5"
 #define MOS6525_TAG     "u2"
-#define CMOS40105_TAG   "u1"
+#define CD40105_TAG     "u1"
 
 #define A12 BIT(offset, 12)
 #define A13 BIT(offset, 13)
@@ -226,7 +226,9 @@ static MACHINE_CONFIG_FRAGMENT( c64_magic_voice )
 	MCFG_TPI6525_OUT_PB_CB(WRITE8(c64_magic_voice_cartridge_device, tpi_pb_w))
 	MCFG_TPI6525_OUT_CA_CB(WRITELINE(c64_magic_voice_cartridge_device, tpi_ca_w))
 	MCFG_TPI6525_OUT_CA_CB(WRITELINE(c64_magic_voice_cartridge_device, tpi_cb_w))
-	MCFG_40105_ADD(CMOS40105_TAG, DEVWRITELINE(MOS6525_TAG, tpi6525_device, i3_w), NOOP)
+
+	MCFG_DEVICE_ADD(CD40105_TAG, CD40105, 0)
+	MCFG_40105_DATA_IN_READY_CB(DEVWRITELINE(MOS6525_TAG, tpi6525_device, i3_w))
 
 	MCFG_SPEAKER_STANDARD_MONO("mono")
 	MCFG_SOUND_ADD(T6721A_TAG, T6721A, XTAL_640kHz)
@@ -265,7 +267,7 @@ c64_magic_voice_cartridge_device::c64_magic_voice_cartridge_device(const machine
 	device_c64_expansion_card_interface(mconfig, *this),
 	m_vslsi(*this, T6721A_TAG),
 	m_tpi(*this, MOS6525_TAG),
-	m_fifo(*this, CMOS40105_TAG),
+	m_fifo(*this, CD40105_TAG),
 	m_exp(*this, C64_EXPANSION_SLOT_TAG), m_ca(0),
 	m_tpi_pb(0x60),
 	m_tpi_pc6(1),
diff --git a/src/devices/bus/c64/midi_passport.cpp b/src/devices/bus/c64/midi_passport.cpp
index 408b7a8..9c09ab4 100644
--- a/src/devices/bus/c64/midi_passport.cpp
+++ b/src/devices/bus/c64/midi_passport.cpp
@@ -62,8 +62,7 @@ static MACHINE_CONFIG_FRAGMENT( c64_passport_midi )
 	MCFG_ACIA6850_TXD_HANDLER(DEVWRITELINE("mdout", midi_port_device, write_txd))
 	MCFG_ACIA6850_IRQ_HANDLER(WRITELINE(c64_passport_midi_cartridge_device, acia_irq_w))
 
-	MCFG_DEVICE_ADD(MC6840_TAG, PTM6840, 0)
-	MCFG_PTM6840_INTERNAL_CLOCK(1021800.0f)
+	MCFG_DEVICE_ADD(MC6840_TAG, PTM6840, 1021800)
 	MCFG_PTM6840_EXTERNAL_CLOCKS(1021800.0f, 1021800.0f, 1021800.0f)
 	MCFG_PTM6840_IRQ_CB(WRITELINE(c64_passport_midi_cartridge_device, ptm_irq_w))
 
diff --git a/src/devices/bus/coco/coco_t4426.cpp b/src/devices/bus/coco/coco_t4426.cpp
new file mode 100644
index 0000000..601e688
--- /dev/null
+++ b/src/devices/bus/coco/coco_t4426.cpp
@@ -0,0 +1,201 @@
+// license:BSD-3-Clause
+// copyright-holders:Joakim Larsson Edstrom
+/***************************************************************************
+ *
+ *  coco_t4426.c
+ *
+ *  Terco T4426 CNC Programming Station multi cart
+ *
+ *  The code here is heavily inspired by coco_pak and coco_232
+ *
+ *  +-------------------------------------------------------------------------------+
+ *  ||__|+-----+    oo   75                               |O ||||||||||||||| O|     |
+ *  |XTL||MC   |    oo  110                                                         |
+ *  |1.8||14411|    oo  ..        +--+ +--+                                         |
+ *  |432||BRG  |    ==  600       |74| |74| +------+                                |
+ *  |MHz||     |    oo  ..        |LS| |LS| |MC1488|                                |
+ *  +---+|     |    oo 7200       |139 |00| +------+                                |
+ *  |    +-----+    oo 9600       +--+ +--+                    +--+                 |
+ *  |                                      +-------------+     |MC|                 |
+ *  |    +-----+   +-----+    +-----+      | EF68B50P    |     |14|                 |
+ *  |    | 2764|   | 2764|    |     |      | ACIA        |     |89|                 |
+ *  |    |     |   |     |    |     |      +-------------+     +--+                 |
+ *  |    |CA   |   |CA   |    |PMOS |                                               |
+ *  |    | 4426|   | 4426|    | 4426|   +-------------------+                       |
+ *  |    |  -6 |   |  -7 |    |     |   |  EP68B21P         |                       |
+ *  |    |     |   |     |    |     |   |  PIA              |                       |
+ *  |    |     |   |     |    +-----+   +-------------------+                       |
+ *  |    +-----+   +-----+                                                          |
+ *  |    +-----+   +-----+    +-----+   +-----+    +-----+   +-----+                |
+ *  |    | 2764|   | 2764|    | 2764|   | 2764|    | 2764|   | 2764|                |
+ *  |    |     |   |     |    |     |   |     |    |     |   |     |                |
+ *  |    |CA   |   |CA   |    |PD   |   |PD   |    |ED   |   |ED   |                |
+ *  |    | 4426|   | 4426|    | 4426|   | 4426|    | 4426|   | 4426|                |
+ *  |    |  -5 |   |  -4 |    |  -3 |   |  -2 |    |  -1 |   |  -0 |                |
+ *  |    |     |   |     |    |     |   |     |    |     |   |     |       OO       |
+ *  |    |     |   |     |    |     |   |     |    |     |   |     |                |
+ *  |    +-----+   +-----+    +-----+   +-----+    +-----+   +-----+                |
+ *  +-------------------------------------------------------------------------------+
+ *
+ ***************************************************************************/
+
+#include "emu.h"
+#include "coco_t4426.h"
+#include "includes/coco.h"
+
+#define LOG_GENERAL 0x01
+#define LOG_SETUP   0x02
+#define LOG_PRINTF  0x04
+
+#define VERBOSE 0 // (LOG_PRINTF | LOG_SETUP  | LOG_GENERAL)
+
+#define LOGMASK(mask, ...)   do { if (VERBOSE & mask) logerror(__VA_ARGS__); } while (0)
+#define LOGLEVEL(mask, level, ...) do { if ((VERBOSE & mask) >= level) logerror(__VA_ARGS__); } while (0)
+
+#define LOG(...)      LOGMASK(LOG_GENERAL, __VA_ARGS__)
+#define LOGSETUP(...) LOGMASK(LOG_SETUP,   __VA_ARGS__)
+
+#if VERBOSE & LOG_PRINTF
+#define logerror printf
+#endif
+
+#ifdef _MSC_VER
+#define FUNCNAME __func__
+#else
+#define FUNCNAME __PRETTY_FUNCTION__
+#endif
+
+/***************************************************************************
+    CONSTANTS
+***************************************************************************/
+
+#define UART_TAG        "acia"
+#define PIA_TAG         "pia"
+#define CARTSLOT_TAG    "t4426"
+
+/***************************************************************************
+    IMPLEMENTATION
+***************************************************************************/
+
+// TODO: Figure out address mapping for these devices
+static MACHINE_CONFIG_FRAGMENT(coco_t4426)
+	MCFG_DEVICE_ADD(UART_TAG, ACIA6850, 0)
+	MCFG_DEVICE_ADD(PIA_TAG, PIA6821, 0)
+MACHINE_CONFIG_END
+
+ROM_START( coco_t4426 )
+	ROM_REGION(0x8000, CARTSLOT_TAG, ROMREGION_ERASE00)
+	// First of 8 banked ROM:s TODO: Add the banking and the other ROM:s
+	ROM_LOAD("tercoED4426-0-8549-5.3.bin",  0x0000, 0x2000, CRC(45665428) SHA1(ff49a79275772c4c4ab1ae29db662c9b10a744a7))
+
+	// Main cartridge ROM
+	ROM_LOAD("tercoPMOS4426-8549-4.31.bin", 0x2000, 0x1000, CRC(bc65c45c) SHA1(e50cfd1d61e29fe05eb795d8bf6303e7b91ed8e5))
+ROM_END
+
+//**************************************************************************
+//  GLOBAL VARIABLES
+//**************************************************************************
+
+const device_type COCO_T4426 = &device_creator<coco_t4426_device>;
+
+//**************************************************************************
+//  LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+//  coco_t4426_device - constructor
+//-------------------------------------------------
+
+coco_t4426_device::coco_t4426_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, uint32_t clock, const char *shortname, const char *source)
+	: device_t(mconfig, type, name, tag, owner, clock, shortname, source)
+	,device_cococart_interface( mconfig, *this )
+	,m_cart(nullptr)
+	,m_owner(nullptr)
+	,m_autostart(*this, ":" CART_AUTOSTART_TAG)
+	,m_uart(*this, UART_TAG)
+	,m_pia(*this, PIA_TAG)
+{
+}
+
+coco_t4426_device::coco_t4426_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+	: device_t(mconfig, COCO_T4426, "Terco CNC Programming Station 4426 multi cart", tag, owner, clock, "coco_t4426", __FILE__)
+	,device_cococart_interface( mconfig, *this )
+	,m_cart(nullptr)
+	,m_owner(nullptr)
+	,m_autostart(*this, ":" CART_AUTOSTART_TAG)
+	,m_uart(*this, UART_TAG)
+	,m_pia(*this, PIA_TAG)
+{
+}
+
+//-------------------------------------------------
+//  device_start - device-specific startup
+//-------------------------------------------------
+
+void coco_t4426_device::device_start()
+{
+	m_cart = dynamic_cast<device_image_interface *>(owner());
+	m_owner = dynamic_cast<cococart_slot_device *>(owner());
+}
+
+//-------------------------------------------------
+//  machine_config_additions - device-specific
+//  machine configurations
+//-------------------------------------------------
+
+machine_config_constructor coco_t4426_device::device_mconfig_additions() const
+{
+	return MACHINE_CONFIG_NAME( coco_t4426 );
+}
+
+//-------------------------------------------------
+//  rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *coco_t4426_device::device_rom_region() const
+{
+	return ROM_NAME( coco_t4426 );
+}
+
+/*-------------------------------------------------
+    device_reset - device-specific startup
+-------------------------------------------------*/
+
+void coco_t4426_device::device_reset()
+{
+	auto cart_line = cococart_slot_device::line_value::Q;
+	m_owner->cart_set_line(cococart_slot_device::line::CART, cart_line);
+}
+
+/*-------------------------------------------------
+    get_cart_base
+-------------------------------------------------*/
+
+uint8_t* coco_t4426_device::get_cart_base()
+{
+	return memregion(CARTSLOT_TAG)->base();
+}
+
+/*-------------------------------------------------
+    read
+-------------------------------------------------*/
+
+READ8_MEMBER(coco_t4426_device::read)
+{
+	uint8_t result = 0x00;
+
+	LOG("%s()\n", FUNCNAME);
+	LOGSETUP(" * Offs:%02x -> %02x\n", offset, result);
+
+	return result;
+}
+
+/*-------------------------------------------------
+    write
+-------------------------------------------------*/
+
+WRITE8_MEMBER(coco_t4426_device::write)
+{
+	LOG("%s(%02x)\n", FUNCNAME, data);
+	LOGSETUP(" * Offs:%02x <- %02x\n", offset, data);
+}
diff --git a/src/devices/bus/coco/coco_t4426.h b/src/devices/bus/coco/coco_t4426.h
new file mode 100644
index 0000000..72cd86a
--- /dev/null
+++ b/src/devices/bus/coco/coco_t4426.h
@@ -0,0 +1,56 @@
+// license:BSD-3-Clause
+// copyright-holders:Nathan Woods
+#ifndef MAME_BUS_COCO_T4426_H
+#define MAME_BUS_COCO_T4426_H
+
+#pragma once
+
+#include "emu.h"
+#include "cococart.h"
+#include "machine/6850acia.h"
+#include "machine/6821pia.h"
+
+//**************************************************************************
+//  TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> coco_t4426_device
+
+class coco_t4426_device :
+		public device_t,
+		public device_cococart_interface
+{
+public:
+		// construction/destruction
+		coco_t4426_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, uint32_t clock, const char *shortname, const char *source);
+		coco_t4426_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+		// optional information overrides
+		virtual machine_config_constructor device_mconfig_additions() const override;
+		virtual const tiny_rom_entry *device_rom_region() const override;
+
+		virtual uint8_t* get_cart_base() override;
+protected:
+		// device-level overrides
+		virtual void device_start() override;
+		virtual void device_reset() override;
+
+		// internal state
+		device_image_interface *m_cart;
+		cococart_slot_device *m_owner;
+
+		optional_ioport m_autostart;
+
+		virtual DECLARE_READ8_MEMBER(read) override;
+		virtual DECLARE_WRITE8_MEMBER(write) override;
+private:
+		// internal state
+		required_device<acia6850_device> m_uart;
+		required_device<pia6821_device> m_pia;
+};
+
+
+// device type definition
+extern const device_type COCO_T4426;
+
+#endif  /* MAME_BUS_COCO_T4426_H */
diff --git a/src/devices/bus/isbx/isbc_218a.cpp b/src/devices/bus/isbx/isbc_218a.cpp
index 7af071f..32ca4ab 100644
--- a/src/devices/bus/isbx/isbc_218a.cpp
+++ b/src/devices/bus/isbx/isbc_218a.cpp
@@ -43,6 +43,7 @@ FLOPPY_FORMATS_MEMBER( isbc_218a_device::floppy_formats )
 FLOPPY_FORMATS_END
 
 static SLOT_INTERFACE_START( isbc_218a_floppies )
+	SLOT_INTERFACE( "8dd", FLOPPY_8_DSDD )
 	SLOT_INTERFACE( "525dd", FLOPPY_525_DD )
 SLOT_INTERFACE_END
 
@@ -105,6 +106,13 @@ void isbc_218a_device::device_reset()
 {
 	m_reset = false;
 	m_motor = false;
+	// set from jumper all drives must be same type
+	m_fd8 = m_floppy0->get_device()->get_form_factor() == floppy_image::FF_8;
+	if(m_fd8)
+	{
+		m_floppy0->get_device()->mon_w(0);
+		m_fdc->set_rate(500000);
+	}
 }
 
 
@@ -171,7 +179,8 @@ void isbc_218a_device::mcs1_w(address_space &space, offs_t offset, uint8_t data)
 		break;
 	case 4:
 		m_motor = data & 1;
-		m_floppy0->get_device()->mon_w(!(data & 1));
+		if(!m_fd8)
+			m_floppy0->get_device()->mon_w(!(data & 1));
 		break;
 	case 6: m_fdc->tc_w(data & 1); break;
 	}
diff --git a/src/devices/bus/isbx/isbc_218a.h b/src/devices/bus/isbx/isbc_218a.h
index d83d612..9dc0088 100644
--- a/src/devices/bus/isbx/isbc_218a.h
+++ b/src/devices/bus/isbx/isbc_218a.h
@@ -56,7 +56,7 @@ private:
 	required_device<i8272a_device> m_fdc;
 	required_device<floppy_connector> m_floppy0;
 
-	bool m_reset, m_motor;
+	bool m_reset, m_motor, m_fd8;
 };
 
 
diff --git a/src/devices/bus/ti99x/gromport.cpp b/src/devices/bus/ti99x/gromport.cpp
index 8ac6edf..468436a 100644
--- a/src/devices/bus/ti99x/gromport.cpp
+++ b/src/devices/bus/ti99x/gromport.cpp
@@ -2628,7 +2628,7 @@ int rpk_reader::find_file(util::archive_file &zip, const char *filename, uint32_
 /*
     Load a rom resource and put it in a pcb socket instance.
 */
-std::unique_ptr<rpk_socket> rpk_reader::load_rom_resource(util::archive_file &zip, xml_data_node const* rom_resource_node, const char* socketname)
+std::unique_ptr<rpk_socket> rpk_reader::load_rom_resource(util::archive_file &zip, util::xml::data_node const* rom_resource_node, const char* socketname)
 {
 	const char* file;
 	const char* crcstr;
@@ -2693,7 +2693,7 @@ std::unique_ptr<rpk_socket> rpk_reader::load_rom_resource(util::archive_file &zi
 /*
     Load a ram resource and put it in a pcb socket instance.
 */
-std::unique_ptr<rpk_socket> rpk_reader::load_ram_resource(emu_options &options, xml_data_node const* ram_resource_node, const char* socketname, const char* system_name)
+std::unique_ptr<rpk_socket> rpk_reader::load_ram_resource(emu_options &options, util::xml::data_node const* ram_resource_node, const char* socketname, const char* system_name)
 {
 	const char* length_string;
 	const char* ram_type;
@@ -2787,7 +2787,7 @@ rpk* rpk_reader::open(emu_options &options, const char *filename, const char *sy
 	util::archive_file::ptr zipfile;
 
 	std::vector<char> layout_text;
-	xml_data_node *layout_xml = nullptr;
+	util::xml::data_node *layout_xml = nullptr;
 
 	int i;
 
@@ -2816,25 +2816,25 @@ rpk* rpk_reader::open(emu_options &options, const char *filename, const char *sy
 		layout_text[zipfile->current_uncompressed_length()] = '\0';  // Null-terminate
 
 		/* parse the layout text */
-		layout_xml = xml_data_node::string_read(&layout_text[0], nullptr);
+		layout_xml = util::xml::data_node::string_read(&layout_text[0], nullptr);
 		if (!layout_xml) throw rpk_exception(RPK_XML_ERROR);
 
 		// Now we work within the XML tree
 
 		// romset is the root node
-		xml_data_node const *const romset_node = layout_xml->get_child("romset");
+		util::xml::data_node const *const romset_node = layout_xml->get_child("romset");
 		if (!romset_node) throw rpk_exception(RPK_INVALID_LAYOUT, "document element must be <romset>");
 
 		// resources is a child of romset
-		xml_data_node const *const resources_node = romset_node->get_child("resources");
+		util::xml::data_node const *const resources_node = romset_node->get_child("resources");
 		if (!resources_node) throw rpk_exception(RPK_INVALID_LAYOUT, "<romset> must have a <resources> child");
 
 		// configuration is a child of romset; we're actually interested in ...
-		xml_data_node const *const configuration_node = romset_node->get_child("configuration");
+		util::xml::data_node const *const configuration_node = romset_node->get_child("configuration");
 		if (!configuration_node) throw rpk_exception(RPK_INVALID_LAYOUT, "<romset> must have a <configuration> child");
 
 		// ... pcb, which is a child of configuration
-		xml_data_node const *const pcb_node = configuration_node->get_child("pcb");
+		util::xml::data_node const *const pcb_node = configuration_node->get_child("pcb");
 		if (!pcb_node) throw rpk_exception(RPK_INVALID_LAYOUT, "<configuration> must have a <pcb> child");
 
 		// We'll try to find the PCB type on the provided type list.
@@ -2856,7 +2856,7 @@ rpk* rpk_reader::open(emu_options &options, const char *filename, const char *sy
 		if (m_types[i].id==0) throw rpk_exception(RPK_UNKNOWN_PCB_TYPE);
 
 		// Find the sockets and load their respective resource
-		for (xml_data_node const *socket_node = pcb_node->get_first_child();  socket_node != nullptr; socket_node = socket_node->get_next_sibling())
+		for (util::xml::data_node const *socket_node = pcb_node->get_first_child();  socket_node != nullptr; socket_node = socket_node->get_next_sibling())
 		{
 			if (strcmp(socket_node->get_name(), "socket")!=0) throw rpk_exception(RPK_INVALID_LAYOUT, "<pcb> element has only <socket> children");
 			char const *const id = socket_node->get_attribute_string("id", nullptr);
@@ -2866,7 +2866,7 @@ rpk* rpk_reader::open(emu_options &options, const char *filename, const char *sy
 
 			bool found = false;
 			// Locate the resource node
-			for (xml_data_node const *resource_node = resources_node->get_first_child(); resource_node != nullptr; resource_node = resource_node->get_next_sibling())
+			for (util::xml::data_node const *resource_node = resources_node->get_first_child(); resource_node != nullptr; resource_node = resource_node->get_next_sibling())
 			{
 				char const *const resource_name = resource_node->get_attribute_string("id", nullptr);
 				if (!resource_name) throw rpk_exception(RPK_INVALID_LAYOUT, "resource node must have an 'id' attribute");
diff --git a/src/devices/bus/ti99x/gromport.h b/src/devices/bus/ti99x/gromport.h
index fc7546b..ff99585 100644
--- a/src/devices/bus/ti99x/gromport.h
+++ b/src/devices/bus/ti99x/gromport.h
@@ -515,9 +515,9 @@ public:
 	rpk *open(emu_options &options, const char *filename, const char *system_name);
 
 private:
-	int             find_file(util::archive_file &zip, const char *filename, uint32_t crc);
-	std::unique_ptr<rpk_socket> load_rom_resource(util::archive_file &zip, xml_data_node const* rom_resource_node, const char* socketname);
-	std::unique_ptr<rpk_socket> load_ram_resource(emu_options &options, xml_data_node const* ram_resource_node, const char* socketname, const char* system_name);
+	int find_file(util::archive_file &zip, const char *filename, uint32_t crc);
+	std::unique_ptr<rpk_socket> load_rom_resource(util::archive_file &zip, util::xml::data_node const* rom_resource_node, const char* socketname);
+	std::unique_ptr<rpk_socket> load_ram_resource(emu_options &options, util::xml::data_node const* ram_resource_node, const char* socketname, const char* system_name);
 	const pcb_type* m_types;
 };
 
diff --git a/src/devices/cpu/arm/arm.cpp b/src/devices/cpu/arm/arm.cpp
index eb4de54..884b228 100644
--- a/src/devices/cpu/arm/arm.cpp
+++ b/src/devices/cpu/arm/arm.cpp
@@ -635,13 +635,7 @@ void arm_cpu_device::HandleMemSingle( uint32_t insn )
 				rnv = (R15 & ADDRESS_MASK) - off;
 		}
 
-		if (insn & INSN_SDT_W)
-		{
-			SetRegister(rn,rnv);
-			if (ARM_DEBUG_CORE && rn == eR15)
-				logerror("writeback R15 %08x\n", R15);
-		}
-		else if (rn == eR15)
+		if (rn == eR15)
 		{
 			rnv = rnv + 8;
 		}
@@ -685,7 +679,7 @@ void arm_cpu_device::HandleMemSingle( uint32_t insn )
 
 				In other cases, 4 is subracted from R15 here to account for pipelining.
 				*/
-				if ((cpu_read32(rnv)&3)==0)
+				if (m_copro_type == ARM_COPRO_TYPE_VL86C020 || (cpu_read32(rnv)&3)==0)
 					R15 -= 4;
 
 				m_icount -= S_CYCLE + N_CYCLE;
@@ -716,6 +710,18 @@ void arm_cpu_device::HandleMemSingle( uint32_t insn )
 		}
 	}
 
+	/* Do pre-indexing writeback */
+	if ((insn & INSN_SDT_P) && (insn & INSN_SDT_W))
+	{
+		if ((insn & INSN_SDT_L) && rd == rn)
+			SetRegister(rn, GetRegister(rd));
+		else
+			SetRegister(rn, rnv);
+
+		if (ARM_DEBUG_CORE && rn == eR15)
+			logerror("writeback R15 %08x\n", R15);
+	}
+
 	/* Do post-indexing writeback */
 	if (!(insn & INSN_SDT_P)/* && (insn&INSN_SDT_W)*/)
 	{
diff --git a/src/devices/cpu/cop400/cop400.cpp b/src/devices/cpu/cop400/cop400.cpp
index fd0164f..51af8f2 100644
--- a/src/devices/cpu/cop400/cop400.cpp
+++ b/src/devices/cpu/cop400/cop400.cpp
@@ -150,7 +150,10 @@ static ADDRESS_MAP_START( program_2kb, AS_PROGRAM, 8, cop400_cpu_device )
 ADDRESS_MAP_END
 
 static ADDRESS_MAP_START( data_32b, AS_DATA, 8, cop400_cpu_device )
-	AM_RANGE(0x00, 0x1f) AM_RAM
+	AM_RANGE(0x00, 0x07) AM_MIRROR(0x08) AM_RAM
+	AM_RANGE(0x10, 0x17) AM_MIRROR(0x08) AM_RAM
+	AM_RANGE(0x20, 0x27) AM_MIRROR(0x08) AM_RAM
+	AM_RANGE(0x30, 0x37) AM_MIRROR(0x08) AM_RAM
 ADDRESS_MAP_END
 
 static ADDRESS_MAP_START( data_64b, AS_DATA, 8, cop400_cpu_device )
@@ -173,6 +176,7 @@ cop400_cpu_device::cop400_cpu_device(const machine_config &mconfig, device_type
 	, m_program_config("program", ENDIANNESS_LITTLE, 8, program_addr_bits, 0, internal_map_program)
 	, m_data_config("data", ENDIANNESS_LITTLE, 8, data_addr_bits, 0, internal_map_data) // data width is really 4
 	, m_read_l(*this)
+	, m_read_l_tristate(*this)
 	, m_write_l(*this)
 	, m_read_g(*this)
 	, m_write_g(*this)
@@ -231,17 +235,17 @@ cop400_cpu_device::cop400_cpu_device(const machine_config &mconfig, device_type
 }
 
 cop401_cpu_device::cop401_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
-	: cop400_cpu_device(mconfig, COP401, "COP401", tag, owner, clock, "cop401", __FILE__, 9, 5, COP410_FEATURE, 0xf, 0xf, 0, false, false, nullptr, ADDRESS_MAP_NAME(data_32b))
+	: cop400_cpu_device(mconfig, COP401, "COP401", tag, owner, clock, "cop401", __FILE__, 9, 6, COP410_FEATURE, 0xf, 0xf, 0, false, false, nullptr, ADDRESS_MAP_NAME(data_32b))
 {
 }
 
 cop410_cpu_device::cop410_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
-	: cop400_cpu_device(mconfig, COP410, "COP410", tag, owner, clock, "cop410", __FILE__, 9, 5, COP410_FEATURE, 0xf, 0xf, 0, false, false, ADDRESS_MAP_NAME(program_512b), ADDRESS_MAP_NAME(data_32b))
+	: cop400_cpu_device(mconfig, COP410, "COP410", tag, owner, clock, "cop410", __FILE__, 9, 6, COP410_FEATURE, 0xf, 0xf, 0, false, false, ADDRESS_MAP_NAME(program_512b), ADDRESS_MAP_NAME(data_32b))
 {
 }
 
 cop411_cpu_device::cop411_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
-	: cop400_cpu_device(mconfig, COP411, "COP411", tag, owner, clock, "cop411", __FILE__, 9, 5, COP410_FEATURE, 0x7, 0x3, 0, false, false, ADDRESS_MAP_NAME(program_512b), ADDRESS_MAP_NAME(data_32b))
+	: cop400_cpu_device(mconfig, COP411, "COP411", tag, owner, clock, "cop411", __FILE__, 9, 6, COP410_FEATURE, 0x7, 0x3, 0, false, false, ADDRESS_MAP_NAME(program_512b), ADDRESS_MAP_NAME(data_32b))
 {
 }
 
@@ -901,6 +905,7 @@ void cop400_cpu_device::device_start()
 	/* find i/o handlers */
 
 	m_read_l.resolve_safe(0);
+	m_read_l_tristate.resolve_safe(0);
 	m_write_l.resolve_safe();
 	m_read_g.resolve_safe(0);
 	m_write_g.resolve_safe();
diff --git a/src/devices/cpu/cop400/cop400.h b/src/devices/cpu/cop400/cop400.h
index bace471..2f907af 100644
--- a/src/devices/cpu/cop400/cop400.h
+++ b/src/devices/cpu/cop400/cop400.h
@@ -20,6 +20,9 @@
 	cop400_cpu_device::set_read_l_callback(*device, DEVCB_##_devcb);
 #define MCFG_COP400_WRITE_L_CB(_devcb) \
 	cop400_cpu_device::set_write_l_callback(*device, DEVCB_##_devcb);
+// output state when pins are in tri-state, default 0
+#define MCFG_COP400_READ_L_TRISTATE_CB(_devcb) \
+	cop400_cpu_device::set_read_l_tristate_callback(*device, DEVCB_##_devcb);
 
 // G pins: 4-bit bi-directional
 #define MCFG_COP400_READ_G_CB(_devcb) \
@@ -125,6 +128,7 @@ public:
 
 	// static configuration helpers
 	template<class _Object> static devcb_base &set_read_l_callback(device_t &device, _Object object) { return downcast<cop400_cpu_device &>(device).m_read_l.set_callback(object); }
+	template<class _Object> static devcb_base &set_read_l_tristate_callback(device_t &device, _Object object) { return downcast<cop400_cpu_device &>(device).m_read_l_tristate.set_callback(object); }
 	template<class _Object> static devcb_base &set_write_l_callback(device_t &device, _Object object) { return downcast<cop400_cpu_device &>(device).m_write_l.set_callback(object); }
 	template<class _Object> static devcb_base &set_read_g_callback(device_t &device, _Object object) { return downcast<cop400_cpu_device &>(device).m_read_g.set_callback(object); }
 	template<class _Object> static devcb_base &set_write_g_callback(device_t &device, _Object object) { return downcast<cop400_cpu_device &>(device).m_write_g.set_callback(object); }
@@ -176,6 +180,7 @@ protected:
 
 	// i/o handlers
 	devcb_read8 m_read_l;
+	devcb_read8 m_read_l_tristate;
 	devcb_write8 m_write_l;
 	devcb_read8 m_read_g;
 	devcb_write8 m_write_g;
diff --git a/src/devices/cpu/cop400/cop400op.hxx b/src/devices/cpu/cop400/cop400op.hxx
index 1c1d5f6..a99a027 100644
--- a/src/devices/cpu/cop400/cop400op.hxx
+++ b/src/devices/cpu/cop400/cop400op.hxx
@@ -948,6 +948,11 @@ INSTRUCTION( lei )
 	{
 		OUT_L(Q);
 	}
+	else
+	{
+		// tri-state(floating) pins
+		OUT_L(m_read_l_tristate(0, 0xff));
+	}
 }
 
 /*
diff --git a/src/devices/cpu/drcbex64.cpp b/src/devices/cpu/drcbex64.cpp
index 27404d0..2cc0888 100644
--- a/src/devices/cpu/drcbex64.cpp
+++ b/src/devices/cpu/drcbex64.cpp
@@ -287,7 +287,13 @@ static const uint8_t int_register_map[REG_I_COUNT] =
 
 static uint8_t float_register_map[REG_F_COUNT] =
 {
+#ifdef X64_WINDOWS_ABI
 	REG_XMM6, REG_XMM7, REG_XMM8, REG_XMM9, REG_XMM10, REG_XMM11, REG_XMM12, REG_XMM13, REG_XMM14, REG_XMM15
+#else
+	// on AMD x64 ABI, XMM0-7 are FP function args.  since this code has no args, and we
+	// save/restore them around CALLC, they should be safe for our use.
+	REG_XMM0, REG_XMM1, REG_XMM2, REG_XMM3, REG_XMM4, REG_XMM5, REG_XMM6, REG_XMM7
+#endif
 };
 
 // condition mapping table
diff --git a/src/devices/cpu/i8089/i8089_channel.cpp b/src/devices/cpu/i8089/i8089_channel.cpp
index 1b8d86d..cbfd60b 100644
--- a/src/devices/cpu/i8089/i8089_channel.cpp
+++ b/src/devices/cpu/i8089/i8089_channel.cpp
@@ -18,7 +18,7 @@
 //**************************************************************************
 
 #define VERBOSE      1
-#define VERBOSE_DMA  1
+#define VERBOSE_DMA  0
 
 // channel control register fields
 #define CC_TMC     ((m_r[CC].w >>  0) & 0x07)   // terminate on masked compare
@@ -835,13 +835,14 @@ WRITE_LINE_MEMBER( i8089_channel::ext_w )
 {
 	if (VERBOSE)
 		logerror("%s('%s'): ext_w: %d\n", shortname(), tag(), state);
-	if(transferring() && state)
+
+	if (transferring() && state)
 		terminate_dma((CC_TX - 1) * 4);
 }
 
 WRITE_LINE_MEMBER( i8089_channel::drq_w )
 {
-	if (VERBOSE)
+	if (VERBOSE_DMA)
 		logerror("%s('%s'): drq_w: %d\n", shortname(), tag(), state);
 
 	m_drq = state;
diff --git a/src/devices/cpu/i86/i186.cpp b/src/devices/cpu/i86/i186.cpp
index 9bfa878..e923c13 100644
--- a/src/devices/cpu/i86/i186.cpp
+++ b/src/devices/cpu/i86/i186.cpp
@@ -549,14 +549,15 @@ void i80186_cpu_device::execute_run()
 void i80186_cpu_device::device_start()
 {
 	i8086_common_cpu_device::device_start();
-	state_add( I8086_ES, "ES", m_sregs[ES] ).callimport().callexport().formatstr("%04X");
-	state_add( I8086_CS, "CS", m_sregs[CS] ).callimport().callexport().formatstr("%04X");
-	state_add( I8086_SS, "SS", m_sregs[SS] ).callimport().callexport().formatstr("%04X");
-	state_add( I8086_DS, "DS", m_sregs[DS] ).callimport().callexport().formatstr("%04X");
-	state_add( I8086_VECTOR, "V", m_int_vector).callimport().callexport().formatstr("%02X");
-
-	state_add(STATE_GENPC, "GENPC", m_pc).formatstr("%05X");
-	state_add(STATE_GENPCBASE, "CURPC", m_pc).formatstr("%05X");
+	state_add( I8086_ES, "ES", m_sregs[ES] ).formatstr("%04X");
+	state_add( I8086_CS, "CS", m_sregs[CS] ).callimport().formatstr("%04X");
+	state_add( I8086_SS, "SS", m_sregs[SS] ).formatstr("%04X");
+	state_add( I8086_DS, "DS", m_sregs[DS] ).formatstr("%04X");
+	state_add( I8086_VECTOR, "V", m_int_vector).formatstr("%02X");
+
+	state_add( I8086_PC, "PC", m_pc ).callimport().formatstr("%05X");
+	state_add( STATE_GENPCBASE, "CURPC", m_pc ).callimport().formatstr("%05X").noshow();
+	state_add( I8086_HALT, "HALT", m_halt ).mask(1);
 
 	// register for savestates
 	save_item(NAME(m_timer[0].control));
diff --git a/src/devices/cpu/i86/i286.cpp b/src/devices/cpu/i86/i286.cpp
index 4872f6f..c399c30 100644
--- a/src/devices/cpu/i86/i286.cpp
+++ b/src/devices/cpu/i86/i286.cpp
@@ -242,51 +242,93 @@ void i80286_cpu_device::device_start()
 	save_item(NAME(m_amask));
 	save_item(NAME(m_shutdown));
 
-	state_add( I286_ES, "ES", m_sregs[ES] ).callimport().callexport().formatstr("%04X");
-	state_add( I286_ES_BASE, "ESBASE", m_base[ES]).callimport().callexport().formatstr("%06X");
-	state_add( I286_ES_LIMIT, "ESLIMIT", m_limit[ES]).callimport().callexport().formatstr("%04X");
-	state_add( I286_ES_FLAGS, "ESFLAGS", m_rights[ES]).callimport().callexport().formatstr("%02X");
-	state_add( I286_CS, "CS", m_sregs[CS] ).callimport().callexport().formatstr("%04X");
-	state_add( I286_CS_BASE, "CSBASE", m_base[CS]).callimport().callexport().formatstr("%06X");
-	state_add( I286_CS_LIMIT, "CSLIMIT", m_limit[CS]).callimport().callexport().formatstr("%04X");
-	state_add( I286_CS_FLAGS, "CSFLAGS", m_rights[CS]).callimport().callexport().formatstr("%02X");
-	state_add( I286_SS, "SS", m_sregs[SS] ).callimport().callexport().formatstr("%04X");
-	state_add( I286_SS_BASE, "SSBASE", m_base[SS]).callimport().callexport().formatstr("%06X");
-	state_add( I286_SS_LIMIT, "SSLIMIT", m_limit[SS]).callimport().callexport().formatstr("%04X");
-	state_add( I286_SS_FLAGS, "SSFLAGS", m_rights[SS]).callimport().callexport().formatstr("%02X");
-	state_add( I286_DS, "DS", m_sregs[DS] ).callimport().callexport().formatstr("%04X");
-	state_add( I286_DS_BASE, "DSBASE", m_base[DS]).callimport().callexport().formatstr("%06X");
-	state_add( I286_DS_LIMIT, "DSLIMIT", m_limit[DS]).callimport().callexport().formatstr("%04X");
-	state_add( I286_DS_FLAGS, "DSFLAGS", m_rights[DS]).callimport().callexport().formatstr("%02X");
-	state_add( I286_GDTR_BASE, "GDTRBASE", m_gdtr.base).callimport().callexport().formatstr("%06X");
-	state_add( I286_GDTR_LIMIT, "GDTRLIMIT", m_gdtr.limit).callimport().callexport().formatstr("%04X");
-	state_add( I286_IDTR_BASE, "IDTRBASE", m_idtr.base).callimport().callexport().formatstr("%06X");
-	state_add( I286_IDTR_LIMIT, "IDTRLIMIT", m_idtr.limit).callimport().callexport().formatstr("%04X");
-	state_add( I286_LDTR, "LDTR", m_ldtr.sel ).callimport().callexport().formatstr("%04X");
-	state_add( I286_LDTR_BASE, "LDTRBASE", m_ldtr.base).callimport().callexport().formatstr("%06X");
-	state_add( I286_LDTR_LIMIT, "LDTRLIMIT", m_ldtr.limit).callimport().callexport().formatstr("%04X");
-	state_add( I286_LDTR_FLAGS, "LDTRFLAGS", m_ldtr.rights).callimport().callexport().formatstr("%02X");
-	state_add( I286_TR, "TR", m_tr.sel ).callimport().callexport().formatstr("%04X");
-	state_add( I286_TR_BASE, "TRBASE", m_tr.base).callimport().callexport().formatstr("%06X");
-	state_add( I286_TR_LIMIT, "TRLIMIT", m_tr.limit).callimport().callexport().formatstr("%04X");
-	state_add( I286_TR_FLAGS, "TRFLAGS", m_tr.rights).callimport().callexport().formatstr("%02X");
-	state_add( I286_MSW, "MSW", m_msw ).callimport().callexport().formatstr("%04X");
-	state_add( I286_VECTOR, "V", m_int_vector).callimport().callexport().formatstr("%02X");
-
-	state_add(STATE_GENPC, "GENPC", m_pc).callexport().formatstr("%06X");
-	state_add(STATE_GENPCBASE, "CURPC", m_pc).callexport().formatstr("%06X");
+	state_add( I286_ES, "ES", m_sregs[ES] ).formatstr("%04X");
+	state_add( I286_ES_BASE, "ESBASE", m_base[ES]).formatstr("%06X");
+	state_add( I286_ES_LIMIT, "ESLIMIT", m_limit[ES]).formatstr("%04X");
+	state_add( I286_ES_FLAGS, "ESFLAGS", m_rights[ES]).formatstr("%02X");
+	state_add( I286_CS, "CS", m_sregs[CS] ).callimport().formatstr("%04X");
+	state_add( I286_CS_BASE, "CSBASE", m_base[CS]).callimport().formatstr("%06X");
+	state_add( I286_CS_LIMIT, "CSLIMIT", m_limit[CS]).formatstr("%04X");
+	state_add( I286_CS_FLAGS, "CSFLAGS", m_rights[CS]).formatstr("%02X");
+	state_add( I286_SS, "SS", m_sregs[SS] ).formatstr("%04X");
+	state_add( I286_SS_BASE, "SSBASE", m_base[SS]).formatstr("%06X");
+	state_add( I286_SS_LIMIT, "SSLIMIT", m_limit[SS]).formatstr("%04X");
+	state_add( I286_SS_FLAGS, "SSFLAGS", m_rights[SS]).formatstr("%02X");
+	state_add( I286_DS, "DS", m_sregs[DS] ).formatstr("%04X");
+	state_add( I286_DS_BASE, "DSBASE", m_base[DS]).formatstr("%06X");
+	state_add( I286_DS_LIMIT, "DSLIMIT", m_limit[DS]).formatstr("%04X");
+	state_add( I286_DS_FLAGS, "DSFLAGS", m_rights[DS]).formatstr("%02X");
+	state_add( I286_GDTR_BASE, "GDTRBASE", m_gdtr.base).formatstr("%06X");
+	state_add( I286_GDTR_LIMIT, "GDTRLIMIT", m_gdtr.limit).formatstr("%04X");
+	state_add( I286_IDTR_BASE, "IDTRBASE", m_idtr.base).formatstr("%06X");
+	state_add( I286_IDTR_LIMIT, "IDTRLIMIT", m_idtr.limit).formatstr("%04X");
+	state_add( I286_LDTR, "LDTR", m_ldtr.sel ).formatstr("%04X");
+	state_add( I286_LDTR_BASE, "LDTRBASE", m_ldtr.base).formatstr("%06X");
+	state_add( I286_LDTR_LIMIT, "LDTRLIMIT", m_ldtr.limit).formatstr("%04X");
+	state_add( I286_LDTR_FLAGS, "LDTRFLAGS", m_ldtr.rights).formatstr("%02X");
+	state_add( I286_TR, "TR", m_tr.sel ).formatstr("%04X");
+	state_add( I286_TR_BASE, "TRBASE", m_tr.base).formatstr("%06X");
+	state_add( I286_TR_LIMIT, "TRLIMIT", m_tr.limit).formatstr("%04X");
+	state_add( I286_TR_FLAGS, "TRFLAGS", m_tr.rights).formatstr("%02X");
+	state_add( I286_MSW, "MSW", m_msw ).formatstr("%04X");
+	state_add( I286_VECTOR, "V", m_int_vector).formatstr("%02X");
+
+	state_add( I286_PC, "PC", m_pc).callimport().formatstr("%06X");
+	state_add( STATE_GENPCBASE, "CURPC", m_pc ).callimport().formatstr("%06X").noshow();
+	state_add( I8086_HALT, "HALT", m_halt ).mask(1);
+
 	m_out_shutdown_func.resolve_safe();
 }
 
-void i80286_cpu_device::state_string_export(const device_state_entry &entry, std::string &str) const
+
+//-------------------------------------------------
+//  state_import - import state into the device,
+//  after it has been set
+//-------------------------------------------------
+
+void i80286_cpu_device::state_import(const device_state_entry &entry)
 {
 	switch (entry.index())
 	{
-		case STATE_GENPC:
-		case STATE_GENPCBASE:
-			str = string_format("%08X", m_base[CS] + m_ip);
-			break;
+	case I286_IP:
+	case I286_CS_BASE:
+		m_pc = m_base[CS] + m_ip;
+		break;
+
+	case I286_CS:
+		// TODO: should this call data_descriptor to update the current segment?
+		break;
+
+	case STATE_GENPC:
+	case STATE_GENPCBASE:
+		if (m_pc - m_base[CS] > m_limit[CS])
+		{
+			// TODO: should this call data_descriptor instead of ignoring jumps outside the current segment?
+			if (PM)
+			{
+				m_pc = m_base[CS] + m_ip;
+			}
+			else
+			{
+				m_sregs[CS] = m_pc >> 4;
+				m_base[CS] = m_sregs[CS] << 4;
+			}
+		}
+		m_ip = m_pc - m_base[CS];
+		break;
+	}
+}
+
 
+//-------------------------------------------------
+//  state_string_export - export state as a string
+//  for the debugger
+//-------------------------------------------------
+
+void i80286_cpu_device::state_string_export(const device_state_entry &entry, std::string &str) const
+{
+	switch (entry.index())
+	{
 		case STATE_GENFLAGS:
 			{
 				uint16_t flags = CompressFlags();
diff --git a/src/devices/cpu/i86/i286.h b/src/devices/cpu/i86/i286.h
index 82694e1..4b4fb5e 100644
--- a/src/devices/cpu/i86/i286.h
+++ b/src/devices/cpu/i86/i286.h
@@ -10,9 +10,9 @@ extern const device_type I80286;
 
 enum
 {   // same order as I8086 registers
-	I286_PC = 0,
+	I286_PC = STATE_GENPC,
 
-	I286_IP,
+	I286_IP = 1,
 	I286_AX,
 	I286_CX,
 	I286_DX,
@@ -29,7 +29,7 @@ enum
 	I286_DS,
 
 	I286_VECTOR,
-	I286_PENDING,
+	I286_HALT,
 
 	I286_ES_BASE,
 	I286_ES_LIMIT,
@@ -77,7 +77,11 @@ protected:
 	virtual void execute_run() override;
 	virtual void device_reset() override;
 	virtual void device_start() override;
+
+	// device_state_interface overrides
+	virtual void state_import(const device_state_entry &entry) override;
 	virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
+
 	virtual uint32_t execute_input_lines() const override { return 1; }
 	virtual void execute_set_input(int inputnum, int state) override;
 	bool memory_translate(address_spacenum spacenum, int intention, offs_t &address) override;
diff --git a/src/devices/cpu/i86/i86.cpp b/src/devices/cpu/i86/i86.cpp
index 1bcc2bf..b0076d2 100644
--- a/src/devices/cpu/i86/i86.cpp
+++ b/src/devices/cpu/i86/i86.cpp
@@ -267,14 +267,15 @@ void i8086_cpu_device::execute_run()
 void i8086_cpu_device::device_start()
 {
 	i8086_common_cpu_device::device_start();
-	state_add( I8086_ES, "ES", m_sregs[ES] ).callimport().callexport().formatstr("%04X");
-	state_add( I8086_CS, "CS", m_sregs[CS] ).callimport().callexport().formatstr("%04X");
-	state_add( I8086_SS, "SS", m_sregs[SS] ).callimport().callexport().formatstr("%04X");
-	state_add( I8086_DS, "DS", m_sregs[DS] ).callimport().callexport().formatstr("%04X");
-	state_add( I8086_VECTOR, "V", m_int_vector).callimport().callexport().formatstr("%02X");
-
-	state_add(STATE_GENPC, "GENPC", m_pc).callexport().formatstr("%05X");
-	state_add(STATE_GENPCBASE, "CURPC", m_pc).callexport().formatstr("%05X");
+	state_add( I8086_ES, "ES", m_sregs[ES] ).formatstr("%04X");
+	state_add( I8086_CS, "CS", m_sregs[CS] ).callimport().formatstr("%04X");
+	state_add( I8086_SS, "SS", m_sregs[SS] ).formatstr("%04X");
+	state_add( I8086_DS, "DS", m_sregs[DS] ).formatstr("%04X");
+	state_add( I8086_VECTOR, "V", m_int_vector).formatstr("%02X");
+
+	state_add( I8086_PC, "PC", m_pc ).callimport().formatstr("%05X");
+	state_add( STATE_GENPCBASE, "CURPC", m_pc ).callimport().formatstr("%05X").noshow();
+	state_add( I8086_HALT, "HALT", m_halt ).mask(1);
 }
 
 i8086_common_cpu_device::i8086_common_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, uint32_t clock, const char *shortname, const char *source)
@@ -319,15 +320,40 @@ i8086_common_cpu_device::i8086_common_cpu_device(const machine_config &mconfig,
 	memset(m_sregs, 0x00, sizeof(m_sregs));
 }
 
-void i8086_common_cpu_device::state_string_export(const device_state_entry &entry, std::string &str) const
+
+//-------------------------------------------------
+//  state_import - import state into the device,
+//  after it has been set
+//-------------------------------------------------
+
+void i8086_common_cpu_device::state_import(const device_state_entry &entry)
 {
 	switch (entry.index())
 	{
-		case STATE_GENPC:
-		case STATE_GENPCBASE:
-			str = string_format("%08X", (m_sregs[CS] << 4) + m_ip);
-			break;
+	case I8086_IP:
+	case I8086_CS:
+		m_pc = (m_sregs[CS] << 4) + m_ip;
+		break;
+
+	case STATE_GENPC:
+	case STATE_GENPCBASE:
+		if (m_pc - (m_sregs[CS] << 4) > 0xffff)
+			m_sregs[CS] = m_pc >> 4;
+		m_ip = m_pc - (m_sregs[CS] << 4);
+		break;
+	}
+}
 
+
+//-------------------------------------------------
+//  state_string_export - export state as a string
+//  for the debugger
+//-------------------------------------------------
+
+void i8086_common_cpu_device::state_string_export(const device_state_entry &entry, std::string &str) const
+{
+	switch (entry.index())
+	{
 		case STATE_GENFLAGS:
 			{
 				uint16_t flags = CompressFlags();
@@ -385,18 +411,17 @@ void i8086_common_cpu_device::device_start()
 	save_item(NAME(m_halt));
 
 	// Register state for debugger
-//  state_add( I8086_PC, "PC", m_PC ).callimport().callexport().formatstr("%04X");
-	state_add( I8086_IP, "IP", m_ip         ).callimport().callexport().formatstr("%04X");
-	state_add( I8086_AX, "AX", m_regs.w[AX] ).callimport().callexport().formatstr("%04X");
-	state_add( I8086_CX, "CX", m_regs.w[CS] ).callimport().callexport().formatstr("%04X");
-	state_add( I8086_DX, "DX", m_regs.w[DX] ).callimport().callexport().formatstr("%04X");
-	state_add( I8086_BX, "BX", m_regs.w[BX] ).callimport().callexport().formatstr("%04X");
-	state_add( I8086_SP, "SP", m_regs.w[SP] ).callimport().callexport().formatstr("%04X");
-	state_add( I8086_BP, "BP", m_regs.w[BP] ).callimport().callexport().formatstr("%04X");
-	state_add( I8086_SI, "SI", m_regs.w[SI] ).callimport().callexport().formatstr("%04X");
-	state_add( I8086_DI, "DI", m_regs.w[DI] ).callimport().callexport().formatstr("%04X");
-
-	state_add(STATE_GENFLAGS, "GENFLAGS", m_TF).callimport().callexport().formatstr("%16s").noshow();
+	state_add( I8086_IP, "IP", m_ip         ).callimport().formatstr("%04X");
+	state_add( I8086_AX, "AX", m_regs.w[AX] ).formatstr("%04X");
+	state_add( I8086_CX, "CX", m_regs.w[CS] ).formatstr("%04X");
+	state_add( I8086_DX, "DX", m_regs.w[DX] ).formatstr("%04X");
+	state_add( I8086_BX, "BX", m_regs.w[BX] ).formatstr("%04X");
+	state_add( I8086_SP, "SP", m_regs.w[SP] ).formatstr("%04X");
+	state_add( I8086_BP, "BP", m_regs.w[BP] ).formatstr("%04X");
+	state_add( I8086_SI, "SI", m_regs.w[SI] ).formatstr("%04X");
+	state_add( I8086_DI, "DI", m_regs.w[DI] ).formatstr("%04X");
+
+	state_add(STATE_GENFLAGS, "GENFLAGS", m_TF).formatstr("%16s").noshow();
 
 	m_icountptr = &m_icount;
 
diff --git a/src/devices/cpu/i86/i86.h b/src/devices/cpu/i86/i86.h
index 9013de5..ecdf97a 100644
--- a/src/devices/cpu/i86/i86.h
+++ b/src/devices/cpu/i86/i86.h
@@ -20,10 +20,10 @@ extern const device_type I8088;
 
 enum
 {
-	I8086_PC=0,
-	I8086_IP, I8086_AX, I8086_CX, I8086_DX, I8086_BX, I8086_SP, I8086_BP, I8086_SI, I8086_DI,
+	I8086_PC = STATE_GENPC,
+	I8086_IP = 1, I8086_AX, I8086_CX, I8086_DX, I8086_BX, I8086_SP, I8086_BP, I8086_SI, I8086_DI,
 	I8086_FLAGS, I8086_ES, I8086_CS, I8086_SS, I8086_DS,
-	I8086_VECTOR, I8086_PENDING
+	I8086_VECTOR, I8086_HALT
 };
 
 
@@ -127,6 +127,7 @@ protected:
 	virtual offs_t disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) override;
 
 	// device_state_interface overrides
+	virtual void state_import(const device_state_entry &entry) override;
 	virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
 
 	virtual void interrupt(int int_num, int trap = 1);
diff --git a/src/devices/cpu/i960/i960.cpp b/src/devices/cpu/i960/i960.cpp
index 1f9db2d..9bc4386 100644
--- a/src/devices/cpu/i960/i960.cpp
+++ b/src/devices/cpu/i960/i960.cpp
@@ -106,6 +106,13 @@ uint32_t i960_cpu_device::get_ea(uint32_t opcode)
 		case 0x4:
 			return m_r[abase];
 
+		case 0x5:   // address of this instruction + the offset dword + 8
+			// which in reality is "address of next instruction + the offset dword"
+			ret = m_direct->read_dword(m_IP);
+			m_IP += 4;
+			ret += m_IP;
+			return ret;
+
 		case 0x7:
 			return m_r[abase] + (m_r[index] << scale);
 
@@ -357,6 +364,14 @@ void i960_cpu_device::bxx(uint32_t opcode, int mask)
 {
 	if(m_AC & mask) {
 		m_IP += get_disp(opcode);
+		m_IP &= ~3;
+	}
+}
+
+void i960_cpu_device::fxx(uint32_t opcode, int mask)
+{
+	if(m_AC & mask) {
+		fatalerror("Taking the fault on a FAULT insn not yet supported\n");
 	}
 }
 
@@ -364,6 +379,7 @@ void i960_cpu_device::bxx_s(uint32_t opcode, int mask)
 {
 	if(m_AC & mask) {
 		m_IP += get_disp_s(opcode);
+		m_IP &= ~3;
 	}
 }
 
@@ -642,6 +658,48 @@ void i960_cpu_device::execute_op(uint32_t opcode)
 			bxx(opcode, 7);
 			break;
 
+		case 0x18: // faultno
+			m_icount--;
+			if(!(m_AC & 7)) {
+				m_IP += get_disp(opcode);
+			}
+			break;
+
+		case 0x19: // faultg
+			m_icount--;
+			fxx(opcode, 1);
+			break;
+
+		case 0x1a: // faulte
+			m_icount--;
+			fxx(opcode, 2);
+			break;
+
+		case 0x1b: // faultge
+			m_icount--;
+			fxx(opcode, 3);
+			break;
+
+		case 0x1c: // faultl
+			m_icount--;
+			fxx(opcode, 4);
+			break;
+
+		case 0x1d: // faultne
+			m_icount--;
+			fxx(opcode, 5);
+			break;
+
+		case 0x1e: // faultle
+			m_icount--;
+			fxx(opcode, 6);
+			break;
+
+		case 0x1f: // faulto
+			m_icount--;
+			fxx(opcode, 7);
+			break;
+
 		case 0x20: // testno
 			m_icount--;
 			if(!(m_AC & 7))
@@ -1069,6 +1127,20 @@ void i960_cpu_device::execute_op(uint32_t opcode)
 				set_ri(opcode, t2-1);
 				break;
 
+			case 0xc: // scanbyte
+				m_icount -= 2;
+				m_AC &= ~7;     // clear CC
+				t1 = get_1_ri(opcode);
+				t2 = get_2_ri(opcode);
+				if ((t1 & 0xff000000) == (t2 & 0xff000000) ||
+					(t1 & 0x00ff0000) == (t2 & 0x00ff0000) ||
+					(t1 & 0x0000ff00) == (t2 & 0x0000ff00) ||
+					(t1 & 0x000000ff) == (t2 & 0x000000ff))
+				{
+					m_AC |= 2;
+				}
+				break;
+
 			case 0xe: // chkbit
 				m_icount -= 2;
 				t1 = get_1_ri(opcode) & 0x1f;
@@ -1305,6 +1377,17 @@ void i960_cpu_device::execute_op(uint32_t opcode)
 
 		case 0x66:
 			switch((opcode >> 7) & 0xf) {
+			case 0x0: // calls
+				t1 = get_1_ri(opcode);
+				t2 = m_program->read_dword(m_SAT + 152);    // get pointer to system procedure table
+				t2 = m_program->read_dword(t2 + 48 + (t1 * 4));
+				if ((t2 & 3) != 0)
+				{
+					fatalerror("I960: system calls that jump into supervisor mode aren't yet supported\n");
+				}
+				do_call(t2, 0, m_r[I960_SP]);
+				break;
+
 			case 0xd: // flushreg
 				if (m_rcache_pos > 4)
 				{
diff --git a/src/devices/cpu/i960/i960.h b/src/devices/cpu/i960/i960.h
index 12de144..64c1eb4 100644
--- a/src/devices/cpu/i960/i960.h
+++ b/src/devices/cpu/i960/i960.h
@@ -161,6 +161,7 @@ private:
 	void cmp_d(double v1, double v2);
 	void bxx(uint32_t opcode, int mask);
 	void bxx_s(uint32_t opcode, int mask);
+	void fxx(uint32_t opcode, int mask);
 	void test(uint32_t opcode, int mask);
 	void execute_op(uint32_t opcode);
 	void take_interrupt(int vector, int lvl);
diff --git a/src/devices/cpu/i960/i960dis.cpp b/src/devices/cpu/i960/i960dis.cpp
index 4def96d..43f8101 100644
--- a/src/devices/cpu/i960/i960dis.cpp
+++ b/src/devices/cpu/i960/i960dis.cpp
@@ -22,7 +22,7 @@ static const mnemonic_t mnemonic[256] = {
 	{ "b", 8 }, { "call", 8 }, { "ret", 9 }, { "bal", 8 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 },
 
 	{ "bno", 8 }, { "bg", 8 }, { "be", 8 }, { "bge", 8 }, { "bl", 8 }, { "bne", 8 }, { "ble", 8 }, { "bo", 8 }, // 10
-	{ "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 },
+	{ "faultno", 0 }, { "faultg", 0 }, { "faulte", 0 }, { "faultge", 0 }, { "faultl", 0 }, { "faultne", 0 }, { "faultle", 0 }, { "faulto", 0 },
 
 	{ "testno", 10 }, { "testg", 10 }, { "teste", 10 }, { "testge", 10 }, { "testl", 10 }, { "testne", 10 }, { "testle", 10 }, { "testo", 10 }, // 20
 	{ "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 },
diff --git a/src/devices/cpu/m68000/m68kcpu.h b/src/devices/cpu/m68000/m68kcpu.h
index 2d3d7c2..4326735 100644
--- a/src/devices/cpu/m68000/m68kcpu.h
+++ b/src/devices/cpu/m68000/m68kcpu.h
@@ -689,9 +689,15 @@ static inline uint32_t m68ki_ic_readimm16(m68000_base_device *m68k, uint32_t add
 			// do a cache fill if the line is invalid or the tags don't match
 			if ((!m68k->ic_valid[idx]) || (m68k->ic_address[idx] != tag))
 			{
+				// if the cache is frozen, don't update it
+				if (m68k->cacr & M68K_CACR_FI)
+				{
+					return m68k->readimm16(address);
+				}
+
 				uint32_t data = m68k->read32(address & ~3);
 
-//              printf("m68k: doing cache fill at %08x (tag %08x idx %d)\n", address, tag, idx);
+				//printf("m68k: doing cache fill at %08x (tag %08x idx %d)\n", address, tag, idx);
 
 				// if no buserror occurred, validate the tag
 				if (!m68k->mmu_tmp_buserror_occurred)
diff --git a/src/devices/cpu/m68000/makefile b/src/devices/cpu/m68000/makefile
index be25a06..e98bbe8 100644
--- a/src/devices/cpu/m68000/makefile
+++ b/src/devices/cpu/m68000/makefile
@@ -23,7 +23,7 @@ clean:
 	- at rm -f m68kmake$(EXE)
 	- at rm -f m68kmake.o
 	- at rm -f m68kops.*
-	
+
 m68kmake.o: m68kmake.cpp
 	$(SILENT) $(CC) -x c++ -std=c++11 -o "$@" -c "$<"
 
@@ -31,7 +31,7 @@ m68kmake$(EXE) : m68kmake.o
 	@echo Linking $@...
 	$(SILENT) $(CXX) -lstdc++ $^ -o $@
 
-m68kops.cpp: m68kmake$(EXE) 	m68k_in.cpp
+m68kops.cpp: m68kmake$(EXE)     m68k_in.cpp
 	@echo Generating M68K source files...
 	$(SILENT) ./m68kmake$(EXE) . m68k_in.cpp
 
diff --git a/src/devices/cpu/m6805/m6805.cpp b/src/devices/cpu/m6805/m6805.cpp
index b8b9a8c..278505b 100644
--- a/src/devices/cpu/m6805/m6805.cpp
+++ b/src/devices/cpu/m6805/m6805.cpp
@@ -415,6 +415,14 @@ m6805_base_device::m6805_base_device(const machine_config &mconfig, const char *
 {
 }
 
+m6805_base_device::m6805_base_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, const device_type type, const char *name, uint32_t addr_width, address_map_constructor internal_map, const char *shortname, const char *source)
+	: cpu_device(mconfig, type, name, tag, owner, clock, shortname, source),
+	m_program_config("program", ENDIANNESS_BIG, 8, addr_width, 0, internal_map)
+{
+}
+
+
+
 void m6805_base_device::device_start()
 {
 	m_program = &space(AS_PROGRAM);
@@ -448,6 +456,7 @@ void m6805_base_device::device_start()
 }
 
 
+
 void m6805_base_device::device_reset()
 {
 	m_ea.w.l = 0;
@@ -954,6 +963,159 @@ void m68705_device::execute_set_input(int inputnum, int state)
 	}
 }
 
+/* ddr - direction registers */
+
+WRITE8_MEMBER(m68705_new_device::mc68705_ddrA_w)
+{
+	m_ddrA = data;
+}
+
+WRITE8_MEMBER(m68705_new_device::mc68705_ddrB_w)
+{
+	m_ddrB = data;
+}
+
+WRITE8_MEMBER(m68705_new_device::mc68705_ddrC_w)
+{
+	m_ddrC = data;
+}
+
+/* read ports */
+
+READ8_MEMBER(m68705_new_device::mc68705_portA_r)
+{
+	m_portA_in = m_portA_cb_r(0, ~m_ddrA); // pass the direction register as mem_mask so that externally we know which lines were actually pulled
+	uint8_t res = (m_portA_out & m_ddrA) | (m_portA_in & ~m_ddrA);
+	return res;
+
+}
+
+READ8_MEMBER(m68705_new_device::mc68705_portB_r)
+{
+	m_portB_in = m_portB_cb_r(0, ~m_ddrB);
+	uint8_t res = (m_portB_out & m_ddrB) | (m_portB_in & ~m_ddrB);
+	return res;
+}
+
+READ8_MEMBER(m68705_new_device::mc68705_portC_r)
+{
+	m_portC_in = m_portC_cb_r(0, ~m_ddrC);
+	uint8_t res = (m_portC_out & m_ddrC) | (m_portC_in & ~m_ddrC);
+	return res;
+}
+
+/* write ports */
+
+WRITE8_MEMBER(m68705_new_device::mc68705_portA_w)
+{
+	m_portA_cb_w(0, data, m_ddrA); // pass the direction register as mem_mask so that externally we know which lines were actually pushed
+	m_portA_out = data;
+}
+
+WRITE8_MEMBER(m68705_new_device::mc68705_portB_w)
+{
+	m_portB_cb_w(0, data, m_ddrB);
+	m_portB_out = data;
+}
+
+WRITE8_MEMBER(m68705_new_device::mc68705_portC_w)
+{
+	m_portC_cb_w(0, data, m_ddrC);
+	m_portC_out = data;
+}
+
+/*
+
+The 68(7)05 peripheral memory map:
+Common for Px, Rx, Ux parts:
+0x00: Port A data (RW)
+0x01: Port B data (RW)
+0x02: Port C data (RW) [top 4 bits do nothing (read as 1s) on Px parts, work as expected on Rx, Ux parts]
+0x03: [Port D data (RW), only on Rx, Ux parts]
+0x04: Port A DDR (Write only, reads as 0xFF)
+0x05: Port B DDR (Write only, reads as 0xFF)
+0x06: Port C DDR (Write only, reads as 0xFF) [top 4 bits do nothing on Px parts, work as expected on Rx, Ux parts]
+0x07: Unused (reads as 0xFF?)
+0x08: Timer Data Register (RW; acts as ram when timer isn't counting, otherwise decrements once per prescaler expiry)
+0x09: Timer Control Register (RW; on certain mask part and when MOR bit 6 is not set, all bits are RW except bit 3 which
+always reads as zero. when MOR bit 6 is set and on all mask parts except one listed in errata in the 6805 daatsheet,
+the top two bits are RW, bottom 6 always read as 1 and writes do nothing; on the errata chip, bit 3 is writable and
+clears the prescaler, reads as zero)
+0x0A: [Miscellaneous Register, only on Rx, Sx, Ux parts]
+0x0B: [Eprom parts: Programming Control Register (write only?, low 3 bits; reads as 0xFF?); Unused (reads as 0xFF?) on
+Mask parts]
+0x0C: Unused (reads as 0xFF?)
+0x0D: Unused (reads as 0xFF?)
+0x0E: [A/D control register, only on Rx, Ux, Sx parts]
+0x0F: [A/D result register, only on Rx, Ux, Sx parts]
+0x10-0x7f: internal ram; SP can only point to 0x60-0x7F. Rx parts have an unused hole from 0x10-0x3F (reads as 0xFF?)
+0x80-0xFF: Page 0 user rom
+The remainder of the memory map differs here between parts, see appropriate datasheet for each part.
+The four vectors are always stored in big endian form as the last 8 bytes of the address space.
+
+Sx specific differences:
+0x02: Port C data (RW) [top 6 bits do nothing (read as 1s) on Sx parts]
+0x06: Port C DDR (Write only, reads as 0xFF) [top 6 bits do nothing on Sx parts]
+0x0B: Timer 2 Data Register MSB
+0x0C: Timer 2 Data Register LSB
+0x0D: Timer 2 Control Register
+0x10: SPI Data Register
+0x11: SPI Control Register
+0x12-0x3F: Unused (reads as 0xFF?)
+
+MOR ADDRESS: Mask Option Register; does not exist on R2 and several other but not all mask parts, located at 0x784 on Px parts
+
+Rx Parts: 40 pins; address space is 0x000-0xfff with an unused hole at 0x10-0x3f and and 0x100-0x7BF; has A/D converter, Ports A-D;
+eprom parts have MOR at 0xF38; mask parts have selftest rom at similar area; selftest roms differ between the U2 and U3 versions
+
+Px Parts: 28 pins; address space is 0x000-0x7ff; eprom parts have MOR at 0x784 and bootstrap rom at 0x785-0x7f7; mask parts have a
+selftest rom at similar area; port c is just 4 bits.
+
+Sx Parts: 40 pins; address space is 0x000-0xfff with an unused hole at 0x12-0x3f and and 0x100-0x9BF; has A/D converter; has SPI
+serial; port C is just two bits; has an extra 16-bit timer compared to Ux/Rx; selftest rom at 0xF00-0xFF7
+
+Ux Parts: 40 pins; address space is 0x000-0xfff; has A/D converter, Ports A-D; eprom parts have MOR at 0xF38; mask parts have
+selftest rom at similar area; selftest roms differ between the U2 and U3 versions
+
+*/
+
+ADDRESS_MAP_START( m68705_internal_map, AS_PROGRAM, 8, m68705_new_device )
+	AM_RANGE(0x000, 0x000) AM_READWRITE(mc68705_portA_r, mc68705_portA_w)
+	AM_RANGE(0x001, 0x001) AM_READWRITE(mc68705_portB_r, mc68705_portB_w)
+	AM_RANGE(0x002, 0x002) AM_READWRITE(mc68705_portC_r, mc68705_portC_w)
+	AM_RANGE(0x004, 0x004) AM_WRITE(mc68705_ddrA_w)
+	AM_RANGE(0x005, 0x005) AM_WRITE(mc68705_ddrB_w)
+	AM_RANGE(0x006, 0x006) AM_WRITE(mc68705_ddrC_w)
+
+	AM_RANGE(0x010, 0x07f) AM_RAM
+	AM_RANGE(0x080, 0x7ff) AM_ROM
+ADDRESS_MAP_END
+
+void m68705_new_device::device_start()
+{
+	m68705_device::device_start();
+
+	save_item(NAME(m_portA_in));
+	save_item(NAME(m_portB_in));
+	save_item(NAME(m_portC_in));
+
+	save_item(NAME(m_portA_out));
+	save_item(NAME(m_portB_out));
+	save_item(NAME(m_portC_out));
+
+	save_item(NAME(m_ddrA));
+	save_item(NAME(m_ddrB));
+	save_item(NAME(m_ddrC));
+
+	m_portA_cb_w.resolve_safe();
+	m_portB_cb_w.resolve_safe();
+	m_portC_cb_w.resolve_safe();
+
+	m_portA_cb_r.resolve_safe(0xff);
+	m_portB_cb_r.resolve_safe(0xff);
+	m_portC_cb_r.resolve_safe(0xff);
+
+}
 
 /****************************************************************************
  * HD63705 section
@@ -1000,4 +1162,5 @@ void hd63705_device::execute_set_input(int inputnum, int state)
 const device_type M6805 = &device_creator<m6805_device>;
 const device_type M68HC05EG = &device_creator<m68hc05eg_device>;
 const device_type M68705 = &device_creator<m68705_device>;
+const device_type M68705_NEW = &device_creator<m68705_new_device>;
 const device_type HD63705 = &device_creator<hd63705_device>;
diff --git a/src/devices/cpu/m6805/m6805.h b/src/devices/cpu/m6805/m6805.h
index 29493af..24b75f5 100644
--- a/src/devices/cpu/m6805/m6805.h
+++ b/src/devices/cpu/m6805/m6805.h
@@ -17,6 +17,7 @@ class m6805_device;
 extern const device_type M6805;
 extern const device_type M68HC05EG;
 extern const device_type M68705;
+extern const device_type M68705_NEW;
 extern const device_type HD63705;
 
 // ======================> m6805_base_device
@@ -27,6 +28,7 @@ class m6805_base_device : public cpu_device
 public:
 	// construction/destruction
 	m6805_base_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, const device_type type, const char *name, uint32_t addr_width, const char *shortname, const char *source);
+	m6805_base_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, const device_type type, const char *name, uint32_t addr_width, address_map_constructor internal_map, const char *shortname, const char *source);
 
 protected:
 	// device-level overrides
@@ -328,6 +330,10 @@ public:
 	m68705_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
 		: m6805_base_device(mconfig, tag, owner, clock, M68705, "M68705", 12, "m68705", __FILE__) { }
 
+	m68705_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, const device_type type, const char *name, uint32_t addr_width, address_map_constructor internal_map, const char *shortname, const char *source)
+		: m6805_base_device(mconfig, tag, owner, clock, type, name, addr_width, internal_map, shortname, source) { }
+
+
 protected:
 	// device-level overrides
 	virtual void device_reset() override;
@@ -337,6 +343,106 @@ protected:
 	virtual void interrupt() override;
 };
 
+// ======================> m68705_new_device
+
+ADDRESS_MAP_EXTERN(m68705_internal_map, 8);
+
+
+#define MCFG_M68705_PORTA_W_CB(_devcb) \
+	m68705_new_device::set_portA_cb_w(*device, DEVCB_##_devcb);
+
+#define MCFG_M68705_PORTB_W_CB(_devcb) \
+	m68705_new_device::set_portB_cb_w(*device, DEVCB_##_devcb);
+
+#define MCFG_M68705_PORTC_W_CB(_devcb) \
+	m68705_new_device::set_portC_cb_w(*device, DEVCB_##_devcb);
+
+#define MCFG_M68705_PORTA_R_CB(_devcb) \
+	m68705_new_device::set_portA_cb_r(*device, DEVCB_##_devcb);
+
+#define MCFG_M68705_PORTB_R_CB(_devcb) \
+	m68705_new_device::set_portB_cb_r(*device, DEVCB_##_devcb);
+
+#define MCFG_M68705_PORTC_R_CB(_devcb) \
+	m68705_new_device::set_portC_cb_r(*device, DEVCB_##_devcb);
+
+
+class m68705_new_device : public m68705_device
+{
+public:
+	// construction/destruction
+	m68705_new_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+		: m68705_device(mconfig, tag, owner, clock, M68705_NEW, "M68705 (NEW)", 11, ADDRESS_MAP_NAME( m68705_internal_map ), "m68705_new", __FILE__),
+			m_portA_in(0),
+			m_portB_in(0),
+			m_portC_in(0),
+			m_portA_out(0),
+			m_portB_out(0),
+			m_portC_out(0),
+			m_ddrA(0),
+			m_ddrB(0),
+			m_ddrC(0),
+			m_portA_cb_w(*this),
+			m_portB_cb_w(*this),
+			m_portC_cb_w(*this),
+			m_portA_cb_r(*this),
+			m_portB_cb_r(*this),
+			m_portC_cb_r(*this)
+		{ }
+
+	// static configuration helpers
+	template<class _Object> static devcb_base &set_portA_cb_w(device_t &device, _Object object) { return downcast<m68705_new_device &>(device).m_portA_cb_w.set_callback(object); }
+	template<class _Object> static devcb_base &set_portB_cb_w(device_t &device, _Object object) { return downcast<m68705_new_device &>(device).m_portB_cb_w.set_callback(object); }
+	template<class _Object> static devcb_base &set_portC_cb_w(device_t &device, _Object object) { return downcast<m68705_new_device &>(device).m_portC_cb_w.set_callback(object); }
+
+	template<class _Object> static devcb_base &set_portA_cb_r(device_t &device, _Object object) { return downcast<m68705_new_device &>(device).m_portA_cb_r.set_callback(object); }
+	template<class _Object> static devcb_base &set_portB_cb_r(device_t &device, _Object object) { return downcast<m68705_new_device &>(device).m_portB_cb_r.set_callback(object); }
+	template<class _Object> static devcb_base &set_portC_cb_r(device_t &device, _Object object) { return downcast<m68705_new_device &>(device).m_portC_cb_r.set_callback(object); }
+
+	DECLARE_READ8_MEMBER(mc68705_portA_r);
+	DECLARE_READ8_MEMBER(mc68705_portB_r);
+	DECLARE_READ8_MEMBER(mc68705_portC_r);
+
+	DECLARE_WRITE8_MEMBER(mc68705_portA_w);
+	DECLARE_WRITE8_MEMBER(mc68705_portB_w);
+	DECLARE_WRITE8_MEMBER(mc68705_portC_w);
+
+	DECLARE_WRITE8_MEMBER(mc68705_ddrA_w);
+	DECLARE_WRITE8_MEMBER(mc68705_ddrB_w);
+	DECLARE_WRITE8_MEMBER(mc68705_ddrC_w);
+
+protected:
+
+	uint8_t m_portA_in;
+	uint8_t m_portB_in;
+	uint8_t m_portC_in;
+
+	uint8_t m_portA_out;
+	uint8_t m_portB_out;
+	uint8_t m_portC_out;
+
+	uint8_t m_ddrA;
+	uint8_t m_ddrB;
+	uint8_t m_ddrC;
+
+	/* Callbacks */
+	devcb_write8 m_portA_cb_w;
+	devcb_write8 m_portB_cb_w;
+	devcb_write8 m_portC_cb_w;
+
+	devcb_read8 m_portA_cb_r;
+	devcb_read8 m_portB_cb_r;
+	devcb_read8 m_portC_cb_r;
+
+
+	// device-level overrides
+	virtual void device_start() override;
+
+//  virtual void execute_set_input(int inputnum, int state) override;
+
+//  virtual void interrupt() override;
+};
+
 // ======================> hd63705_device
 
 class hd63705_device : public m6805_base_device
diff --git a/src/devices/cpu/mb86235/mb86235.cpp b/src/devices/cpu/mb86235/mb86235.cpp
index c264152..44a1d59 100644
--- a/src/devices/cpu/mb86235/mb86235.cpp
+++ b/src/devices/cpu/mb86235/mb86235.cpp
@@ -1,5 +1,5 @@
 // license:BSD-3-Clause
-// copyright-holders:Angelo Salese, ElSemi
+// copyright-holders:Angelo Salese, ElSemi, Ville Linde
 /*****************************************************************************
  *
  * MB86235 "TGPx4" (c) Fujitsu
@@ -14,69 +14,170 @@
 #include "emu.h"
 #include "debugger.h"
 #include "mb86235.h"
+#include "mb86235fe.h"
 
 
-const device_type MB86235 = &device_creator<mb86235_cpu_device>;
+#define ENABLE_DRC      0
 
 
+#define CACHE_SIZE                      (1 * 1024 * 1024)
+#define COMPILE_BACKWARDS_BYTES         128
+#define COMPILE_FORWARDS_BYTES          512
+#define COMPILE_MAX_INSTRUCTIONS        ((COMPILE_BACKWARDS_BYTES/4) + (COMPILE_FORWARDS_BYTES/4))
+#define COMPILE_MAX_SEQUENCE            64
 
 
 
-#define mb86235_readop(A) m_program->read_dword(A)
-#define mb86235_readmem(A) m_program->read_dword(A)
-#define mb86235_writemem(A,B) m_program->write_dword((A),B)
+const device_type MB86235 = &device_creator<mb86235_device>;
 
 
-/***********************************
- *  illegal opcodes
- ***********************************/
-void mb86235_cpu_device::mb86235_illegal()
+static ADDRESS_MAP_START(internal_abus, AS_DATA, 32, mb86235_device)
+	AM_RANGE(0x000000, 0x0003ff) AM_RAM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START(internal_bbus, AS_IO, 32, mb86235_device)
+	AM_RANGE(0x000000, 0x0003ff) AM_RAM
+ADDRESS_MAP_END
+
+
+
+/* Execute cycles */
+void mb86235_device::execute_run()
 {
-	//logerror("mb86235 illegal opcode at 0x%04x\n", m_pc);
-	m_icount -= 1;
+#if ENABLE_DRC
+	run_drc();
+#else
+	m_core->icount = 0;
+#endif
 }
 
-/* Execute cycles */
-void mb86235_cpu_device::execute_run()
+
+void mb86235_device::device_start()
 {
-	uint32_t opcode;
+	m_program = &space(AS_PROGRAM);
+	m_direct = &m_program->direct();
+	m_dataa = &space(AS_DATA);
+	m_datab = &space(AS_IO);
+
+	m_core = (mb86235_internal_state *)m_cache.alloc_near(sizeof(mb86235_internal_state));
+	memset(m_core, 0, sizeof(mb86235_internal_state));
+
+
+	// init UML generator
+	uint32_t umlflags = 0;
+	m_drcuml = std::make_unique<drcuml_state>(*this, m_cache, umlflags, 1, 24, 0);
+
+	// add UML symbols
+	m_drcuml->symbol_add(&m_core->pc, sizeof(m_core->pc), "pc");
+	m_drcuml->symbol_add(&m_core->icount, sizeof(m_core->icount), "icount");
 
-	do
+	for (int i = 0; i < 8; i++)
 	{
-		debugger_instruction_hook(this, m_pc);
+		char buf[10];
+		sprintf(buf, "aa%d", i);
+		m_drcuml->symbol_add(&m_core->aa[i], sizeof(m_core->aa[i]), buf);
+		sprintf(buf, "ab%d", i);
+		m_drcuml->symbol_add(&m_core->ab[i], sizeof(m_core->ab[i]), buf);
+		sprintf(buf, "ma%d", i);
+		m_drcuml->symbol_add(&m_core->ma[i], sizeof(m_core->ma[i]), buf);
+		sprintf(buf, "mb%d", i);
+		m_drcuml->symbol_add(&m_core->mb[i], sizeof(m_core->mb[i]), buf);
+		sprintf(buf, "ar%d", i);
+		m_drcuml->symbol_add(&m_core->ar[i], sizeof(m_core->ar[i]), buf);
+	}
 
-		opcode = mb86235_readop(m_pc);
-		//m_pc++;
+	m_drcuml->symbol_add(&m_core->flags.az, sizeof(m_core->flags.az), "flags_az");
+	m_drcuml->symbol_add(&m_core->flags.an, sizeof(m_core->flags.an), "flags_an");
+	m_drcuml->symbol_add(&m_core->flags.av, sizeof(m_core->flags.av), "flags_av");
+	m_drcuml->symbol_add(&m_core->flags.au, sizeof(m_core->flags.au), "flags_au");
+	m_drcuml->symbol_add(&m_core->flags.ad, sizeof(m_core->flags.ad), "flags_ad");
+	m_drcuml->symbol_add(&m_core->flags.zc, sizeof(m_core->flags.zc), "flags_zc");
+	m_drcuml->symbol_add(&m_core->flags.il, sizeof(m_core->flags.il), "flags_il");
+	m_drcuml->symbol_add(&m_core->flags.nr, sizeof(m_core->flags.nr), "flags_nr");
+	m_drcuml->symbol_add(&m_core->flags.zd, sizeof(m_core->flags.zd), "flags_zd");
+	m_drcuml->symbol_add(&m_core->flags.mn, sizeof(m_core->flags.mn), "flags_mn");
+	m_drcuml->symbol_add(&m_core->flags.mz, sizeof(m_core->flags.mz), "flags_mz");
+	m_drcuml->symbol_add(&m_core->flags.mv, sizeof(m_core->flags.mv), "flags_mv");
+	m_drcuml->symbol_add(&m_core->flags.mu, sizeof(m_core->flags.mu), "flags_mu");
+	m_drcuml->symbol_add(&m_core->flags.md, sizeof(m_core->flags.md), "flags_md");
 
-		switch( opcode )
-		{
-			default:
-				mb86235_illegal();
-				break;
-		}
 
-	} while( m_icount > 0 );
-}
+	m_drcuml->symbol_add(&m_core->arg0, sizeof(m_core->arg0), "arg0");
+	m_drcuml->symbol_add(&m_core->arg1, sizeof(m_core->arg1), "arg1");
+	m_drcuml->symbol_add(&m_core->arg2, sizeof(m_core->arg2), "arg2");
+	m_drcuml->symbol_add(&m_core->arg3, sizeof(m_core->arg3), "arg3");
+	m_drcuml->symbol_add(&m_core->alutemp, sizeof(m_core->alutemp), "alutemp");
+	m_drcuml->symbol_add(&m_core->multemp, sizeof(m_core->multemp), "multemp");
 
+	m_drcuml->symbol_add(&m_core->pcs_ptr, sizeof(m_core->pcs_ptr), "pcs_ptr");
 
-void mb86235_cpu_device::device_start()
-{
-	m_program = &space(AS_PROGRAM);
 
-	save_item(NAME(m_pc));
-	save_item(NAME(m_flags));
+	m_drcfe = std::make_unique<mb86235_frontend>(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, COMPILE_MAX_SEQUENCE);
+
+	for (int i = 0; i < 8; i++)
+	{
+		m_regmap[i] = uml::mem(&m_core->aa[i]);
+		m_regmap[i + 8] = uml::mem(&m_core->ab[i]);
+		m_regmap[i + 16] = uml::mem(&m_core->ma[i]);
+		m_regmap[i + 24] = uml::mem(&m_core->mb[i]);
+	}
+
 
 	// Register state for debugger
-	//state_add( CP1610_R0, "PC", m_pc ).formatstr("%02X");
-	state_add( STATE_GENPC, "GENPC", m_pc ).noshow();
-	state_add( STATE_GENPCBASE, "CURPC", m_pc ).noshow();
-	state_add( STATE_GENFLAGS, "GENFLAGS", m_flags ).noshow();
+	state_add(MB86235_PC, "PC", m_core->pc).formatstr("%08X");
+	state_add(MB86235_AR0, "AR0", m_core->ar[0]).formatstr("%08X");
+	state_add(MB86235_AR1, "AR1", m_core->ar[1]).formatstr("%08X");
+	state_add(MB86235_AR2, "AR2", m_core->ar[2]).formatstr("%08X");
+	state_add(MB86235_AR3, "AR3", m_core->ar[3]).formatstr("%08X");
+	state_add(MB86235_AR4, "AR4", m_core->ar[4]).formatstr("%08X");
+	state_add(MB86235_AR5, "AR5", m_core->ar[5]).formatstr("%08X");
+	state_add(MB86235_AR6, "AR6", m_core->ar[6]).formatstr("%08X");
+	state_add(MB86235_AR7, "AR7", m_core->ar[7]).formatstr("%08X");
+	state_add(MB86235_AA0, "AA0", m_core->aa[0]).formatstr("%08X");
+	state_add(MB86235_AA1, "AA1", m_core->aa[1]).formatstr("%08X");
+	state_add(MB86235_AA2, "AA2", m_core->aa[2]).formatstr("%08X");
+	state_add(MB86235_AA3, "AA3", m_core->aa[3]).formatstr("%08X");
+	state_add(MB86235_AA4, "AA4", m_core->aa[4]).formatstr("%08X");
+	state_add(MB86235_AA5, "AA5", m_core->aa[5]).formatstr("%08X");
+	state_add(MB86235_AA6, "AA6", m_core->aa[6]).formatstr("%08X");
+	state_add(MB86235_AA7, "AA7", m_core->aa[7]).formatstr("%08X");
+	state_add(MB86235_AB0, "AB0", m_core->ab[0]).formatstr("%08X");
+	state_add(MB86235_AB1, "AB1", m_core->ab[1]).formatstr("%08X");
+	state_add(MB86235_AB2, "AB2", m_core->ab[2]).formatstr("%08X");
+	state_add(MB86235_AB3, "AB3", m_core->ab[3]).formatstr("%08X");
+	state_add(MB86235_AB4, "AB4", m_core->ab[4]).formatstr("%08X");
+	state_add(MB86235_AB5, "AB5", m_core->ab[5]).formatstr("%08X");
+	state_add(MB86235_AB6, "AB6", m_core->ab[6]).formatstr("%08X");
+	state_add(MB86235_AB7, "AB7", m_core->ab[7]).formatstr("%08X");
+	state_add(MB86235_MA0, "MA0", m_core->ma[0]).formatstr("%08X");
+	state_add(MB86235_MA1, "MA1", m_core->ma[1]).formatstr("%08X");
+	state_add(MB86235_MA2, "MA2", m_core->ma[2]).formatstr("%08X");
+	state_add(MB86235_MA3, "MA3", m_core->ma[3]).formatstr("%08X");
+	state_add(MB86235_MA4, "MA4", m_core->ma[4]).formatstr("%08X");
+	state_add(MB86235_MA5, "MA5", m_core->ma[5]).formatstr("%08X");
+	state_add(MB86235_MA6, "MA6", m_core->ma[6]).formatstr("%08X");
+	state_add(MB86235_MA7, "MA7", m_core->ma[7]).formatstr("%08X");
+	state_add(MB86235_MB0, "MB0", m_core->mb[0]).formatstr("%08X");
+	state_add(MB86235_MB1, "MB1", m_core->mb[1]).formatstr("%08X");
+	state_add(MB86235_MB2, "MB2", m_core->mb[2]).formatstr("%08X");
+	state_add(MB86235_MB3, "MB3", m_core->mb[3]).formatstr("%08X");
+	state_add(MB86235_MB4, "MB4", m_core->mb[4]).formatstr("%08X");
+	state_add(MB86235_MB5, "MB5", m_core->mb[5]).formatstr("%08X");
+	state_add(MB86235_MB6, "MB6", m_core->mb[6]).formatstr("%08X");
+	state_add(MB86235_MB7, "MB7", m_core->mb[7]).formatstr("%08X");
+	state_add(STATE_GENPC, "GENPC", m_core->pc ).noshow();
+	state_add(STATE_GENPCBASE, "CURPC", m_core->pc).noshow();
+
+	m_icountptr = &m_core->icount;
 
-	m_icountptr = &m_icount;
+	m_core->fp0 = 0.0f;
 }
 
-void mb86235_cpu_device::device_reset()
+void mb86235_device::device_reset()
 {
+	flush_cache();
+
+	m_core->pc = 0;
 }
 
 #if 0
@@ -102,29 +203,86 @@ void mb86235_cpu_device::execute_set_input(int irqline, int state)
 }
 #endif
 
-mb86235_cpu_device::mb86235_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+mb86235_device::mb86235_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
 	: cpu_device(mconfig, MB86235, "MB86235", tag, owner, clock, "mb86235", __FILE__)
 	, m_program_config("program", ENDIANNESS_LITTLE, 64, 32, -3)
+	, m_dataa_config("data_a", ENDIANNESS_LITTLE, 32, 24, -2, ADDRESS_MAP_NAME(internal_abus))
+	, m_datab_config("data_b", ENDIANNESS_LITTLE, 32, 10, -2, ADDRESS_MAP_NAME(internal_bbus))
+	, m_cache(CACHE_SIZE + sizeof(mb86235_internal_state))
+	, m_drcuml(nullptr)
+	, m_drcfe(nullptr)
 {
 }
 
 
-void mb86235_cpu_device::state_string_export(const device_state_entry &entry, std::string &str) const
+void mb86235_device::state_string_export(const device_state_entry &entry, std::string &str) const
 {
 	switch (entry.index())
 	{
 		case STATE_GENFLAGS:
-			str = string_format("%c%c%c%c",
-				m_flags & 0x80 ? 'S':'.',
-				m_flags & 0x40 ? 'Z':'.',
-				m_flags & 0x20 ? 'V':'.',
-				m_flags & 0x10 ? 'C':'.');
+			str = string_format("?");
 			break;
 	}
 }
 
-offs_t mb86235_cpu_device::disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options)
+offs_t mb86235_device::disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options)
 {
 	extern CPU_DISASSEMBLE( mb86235 );
 	return CPU_DISASSEMBLE_NAME(mb86235)(this, stream, pc, oprom, opram, options);
 }
+
+
+void mb86235_device::fifoin_w(uint64_t data)
+{
+#if ENABLE_DRC
+	if (m_core->fifoin.num >= FIFOIN_SIZE)
+	{
+		fatalerror("fifoin_w: pushing to full fifo");
+	}
+
+	printf("FIFOIN push %08X%08X\n", (uint32_t)(data >> 32), (uint32_t)(data));
+
+	m_core->fifoin.data[m_core->fifoin.wpos] = data;
+
+	m_core->fifoin.wpos++;
+	m_core->fifoin.wpos &= FIFOIN_SIZE-1;
+	m_core->fifoin.num++;
+#endif
+}
+
+bool mb86235_device::is_fifoin_full()
+{
+#if ENABLE_DRC
+	return m_core->fifoin.num >= FIFOIN_SIZE;
+#else
+	return false;
+#endif
+}
+
+uint64_t mb86235_device::fifoout0_r()
+{
+#if ENABLE_DRC
+	if (m_core->fifoout0.num == 0)
+	{
+		fatalerror("fifoout0_r: reading from empty fifo");
+	}
+
+	uint64_t data = m_core->fifoout0.data[m_core->fifoout0.rpos];
+
+	m_core->fifoout0.rpos++;
+	m_core->fifoout0.rpos &= FIFOOUT0_SIZE - 1;
+	m_core->fifoout0.num--;
+	return data;
+#else
+	return 0;
+#endif
+}
+
+bool mb86235_device::is_fifoout0_empty()
+{
+#if ENABLE_DRC
+	return m_core->fifoout0.num == 0;
+#else
+	return false;
+#endif
+}
diff --git a/src/devices/cpu/mb86235/mb86235.h b/src/devices/cpu/mb86235/mb86235.h
index 8a8bd86..99c008a 100644
--- a/src/devices/cpu/mb86235/mb86235.h
+++ b/src/devices/cpu/mb86235/mb86235.h
@@ -11,20 +11,63 @@
 #ifndef __MB86235_H__
 #define __MB86235_H__
 
-#if 0
-enum
-{
-	MB86235_R0=1, MB86235_R1, MB86235_R2, MB86235_R3,
-	MB86235_R4, MB86235_R5, MB86235_R6, MB86235_R7
-};
-#endif
+#include "cpu/drcfe.h"
+#include "cpu/drcuml.h"
+
+class mb86235_frontend;
+
+
+
+
+#define OP_USERFLAG_FIFOIN              0x1
+#define OP_USERFLAG_FIFOOUT0            0x2
+#define OP_USERFLAG_FIFOOUT1            0x4
+#define OP_USERFLAG_REPEAT              0x8
+#define OP_USERFLAG_REPEATED_OP         0x10
+#define OP_USERFLAG_PR_MASK             0x300
+#define OP_USERFLAG_PR_INC              0x100
+#define OP_USERFLAG_PR_DEC              0x200
+#define OP_USERFLAG_PR_ZERO             0x300
+#define OP_USERFLAG_PW_MASK             0xc00
+#define OP_USERFLAG_PW_INC              0x400
+#define OP_USERFLAG_PW_DEC              0x800
+#define OP_USERFLAG_PW_ZERO             0xc00
 
 
-class mb86235_cpu_device :  public cpu_device
+class mb86235_device :  public cpu_device
 {
+	friend class mb86235_frontend;
+
 public:
 	// construction/destruction
-	mb86235_cpu_device(const machine_config &mconfig, const char *_tag, device_t *_owner, uint32_t _clock);
+	mb86235_device(const machine_config &mconfig, const char *_tag, device_t *_owner, uint32_t clock);
+
+	void unimplemented_op();
+	void unimplemented_alu();
+	void unimplemented_control();
+	void unimplemented_double_xfer1();
+	void unimplemented_double_xfer2();
+	void pcs_overflow();
+	void pcs_underflow();
+
+	void fifoin_w(uint64_t data);
+	bool is_fifoin_full();
+	uint64_t fifoout0_r();
+	bool is_fifoout0_empty();
+
+	enum
+	{
+		MB86235_PC = 1,
+		MB86235_AA0, MB86235_AA1, MB86235_AA2, MB86235_AA3, MB86235_AA4, MB86235_AA5, MB86235_AA6, MB86235_AA7,
+		MB86235_AB0, MB86235_AB1, MB86235_AB2, MB86235_AB3, MB86235_AB4, MB86235_AB5, MB86235_AB6, MB86235_AB7,
+		MB86235_MA0, MB86235_MA1, MB86235_MA2, MB86235_MA3, MB86235_MA4, MB86235_MA5, MB86235_MA6, MB86235_MA7,
+		MB86235_MB0, MB86235_MB1, MB86235_MB2, MB86235_MB3, MB86235_MB4, MB86235_MB5, MB86235_MB6, MB86235_MB7,
+		MB86235_AR0, MB86235_AR1, MB86235_AR2, MB86235_AR3, MB86235_AR4, MB86235_AR5, MB86235_AR6, MB86235_AR7,
+	};
+
+	const int FIFOIN_SIZE = 16;
+	const int FIFOOUT0_SIZE = 16;
+	const int FIFOOUT1_SIZE = 16;
 
 protected:
 	// device-level overrides
@@ -39,7 +82,7 @@ protected:
 	//virtual void execute_set_input(int inputnum, int state);
 
 	// device_memory_interface overrides
-	virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const override { return (spacenum == AS_PROGRAM) ? &m_program_config : nullptr; }
+	virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const override { return (spacenum == AS_PROGRAM) ? &m_program_config : ((spacenum == AS_DATA) ? &m_dataa_config : (spacenum == AS_IO) ? &m_datab_config : nullptr); }
 
 	// device_state_interface overrides
 	virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
@@ -49,16 +92,154 @@ protected:
 	virtual uint32_t disasm_max_opcode_bytes() const override { return 8; }
 	virtual offs_t disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) override;
 
+	direct_read_data *m_direct;
+
 private:
-	address_space_config m_program_config;
 
-	uint8_t   m_pc;   /* registers */
-	uint8_t   m_flags;  /* flags */
-	address_space *m_program;
-	int m_icount;
+	struct mb86235_flags
+	{
+		uint32_t az;
+		uint32_t an;
+		uint32_t av;
+		uint32_t au;
+		uint32_t ad;
+		uint32_t zc;
+		uint32_t il;
+		uint32_t nr;
+		uint32_t zd;
+		uint32_t mn;
+		uint32_t mz;
+		uint32_t mv;
+		uint32_t mu;
+		uint32_t md;
+	};
+
+	struct fifo
+	{
+		int rpos;
+		int wpos;
+		int num;
+		uint64_t data[16];
+	};
+
+	struct mb86235_internal_state
+	{
+		uint32_t pc;
+		uint32_t aa[8];
+		uint32_t ab[8];
+		uint32_t ma[8];
+		uint32_t mb[8];
+		uint32_t ar[8];
+
+		uint32_t sp;
+		uint32_t eb;
+		uint32_t eo;
+		uint32_t rpc;
+		uint32_t lpc;
+
+		uint32_t prp;
+		uint32_t pwp;
+		uint32_t pr[24];
+
+		uint32_t mod;
+		mb86235_flags flags;
+
+		int icount;
+
+		uint32_t arg0;
+		uint32_t arg1;
+		uint32_t arg2;
+		uint32_t arg3;
+		uint64_t arg64;
+
+		uint32_t pcs[4];
+		int pcs_ptr;
+
+		uint32_t jmpdest;
+		uint32_t alutemp;
+		uint32_t multemp;
+		uint32_t condtemp;
+
+		uint32_t pdr;
+		uint32_t ddr;
+
+		float fp0;
+
+		fifo fifoin;
+		fifo fifoout0;
+		fifo fifoout1;
+	};
+
+	mb86235_internal_state  *m_core;
+
+	uml::parameter   m_regmap[32];
+
+	uml::code_handle *m_entry;                      /* entry point */
+	uml::code_handle *m_nocode;                     /* nocode exception handler */
+	uml::code_handle *m_out_of_cycles;              /* out of cycles exception handler */
+	uml::code_handle *m_clear_fifo_in;
+	uml::code_handle *m_clear_fifo_out0;
+	uml::code_handle *m_clear_fifo_out1;
+	uml::code_handle *m_read_fifo_in;
+	uml::code_handle *m_write_fifo_out0;
+	uml::code_handle *m_write_fifo_out1;
+	uml::code_handle *m_read_abus;
+	uml::code_handle *m_write_abus;
 
-	void mb86235_illegal();
+	address_space_config m_program_config;
+	address_space_config m_dataa_config;
+	address_space_config m_datab_config;
+	drc_cache m_cache;
+	std::unique_ptr<drcuml_state> m_drcuml;
+	std::unique_ptr<mb86235_frontend> m_drcfe;
 
+	address_space *m_program;
+	address_space *m_dataa;
+	address_space *m_datab;
+
+	/* internal compiler state */
+	struct compiler_state
+	{
+		uint32_t cycles;                             /* accumulated cycles */
+		uint8_t  checkints;                          /* need to check interrupts before next instruction */
+		uml::code_label  labelnum;                 /* index for local labels */
+	};
+
+	void run_drc();
+	void flush_cache();
+	void alloc_handle(drcuml_state *drcuml, uml::code_handle **handleptr, const char *name);
+	void compile_block(offs_t pc);
+	void load_fast_iregs(drcuml_block *block);
+	void save_fast_iregs(drcuml_block *block);
+	void static_generate_entry_point();
+	void static_generate_nocode_handler();
+	void static_generate_out_of_cycles();
+	void static_generate_fifo();
+	void static_generate_memory_accessors();
+	void generate_sequence_instruction(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+	void generate_update_cycles(drcuml_block *block, compiler_state *compiler, uml::parameter param, bool allow_exception);
+	bool generate_opcode(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+	void generate_alu(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int aluop, bool alu_temp);
+	void generate_mul(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int mulop, bool mul_temp);
+	void generate_pre_control(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+	void generate_control(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+	void generate_xfer1(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+	void generate_double_xfer1(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+	void generate_xfer2(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+	void generate_double_xfer2(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+	void generate_xfer3(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+	void generate_branch(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+	void generate_ea(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int md, int arx, int ary, int disp);
+	void generate_reg_read(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int reg, uml::parameter dst);
+	void generate_reg_write(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int reg, uml::parameter src);
+	void generate_alumul_input(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int reg, uml::parameter dst, bool fp, bool mul);
+	uml::parameter get_alu1_input(int reg);
+	uml::parameter get_alu_output(int reg);
+	uml::parameter get_mul1_input(int reg);
+	void generate_condition(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int cc, bool n, uml::code_label skip_label, bool condtemp);
+	void generate_branch_target(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int type, int ef2);
+	bool has_register_clash(const opcode_desc *desc, int outreg);
+	bool aluop_has_result(int aluop);
 };
 
 
diff --git a/src/devices/cpu/mb86235/mb86235drc.cpp b/src/devices/cpu/mb86235/mb86235drc.cpp
new file mode 100644
index 0000000..0a27c23
--- /dev/null
+++ b/src/devices/cpu/mb86235/mb86235drc.cpp
@@ -0,0 +1,1889 @@
+// license:BSD-3-Clause
+// copyright-holders:Ville Linde
+
+/******************************************************************************
+
+    MB86235 UML recompiler core
+
+******************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "mb86235.h"
+#include "mb86235fe.h"
+#include "cpu/drcfe.h"
+#include "cpu/drcuml.h"
+#include "cpu/drcumlsh.h"
+
+/*
+    TODO:
+    - check jump condition before parallel ALU/MUL (flags!)
+
+*/
+
+
+
+
+using namespace uml;
+
+
+// map variables
+#define MAPVAR_PC                       M0
+#define MAPVAR_CYCLES                   M1
+
+// exit codes
+#define EXECUTE_OUT_OF_CYCLES           0
+#define EXECUTE_MISSING_CODE            1
+#define EXECUTE_UNMAPPED_CODE           2
+#define EXECUTE_RESET_CACHE             3
+
+
+#define AR(reg)                 mem(&m_core->ar[(reg)])
+#define AA(reg)                 m_regmap[(reg)]
+#define AB(reg)                 m_regmap[(reg)+8]
+#define MA(reg)                 m_regmap[(reg)+16]
+#define MB(reg)                 m_regmap[(reg)+24]
+#define FLAGS_AZ                mem(&m_core->flags.az)
+#define FLAGS_AN                mem(&m_core->flags.an)
+#define FLAGS_AV                mem(&m_core->flags.av)
+#define FLAGS_AU                mem(&m_core->flags.au)
+#define FLAGS_AD                mem(&m_core->flags.ad)
+#define FLAGS_ZC                mem(&m_core->flags.zc)
+#define FLAGS_IL                mem(&m_core->flags.il)
+#define FLAGS_NR                mem(&m_core->flags.nr)
+#define FLAGS_ZD                mem(&m_core->flags.zd)
+#define FLAGS_MN                mem(&m_core->flags.mn)
+#define FLAGS_MZ                mem(&m_core->flags.mz)
+#define FLAGS_MV                mem(&m_core->flags.mv)
+#define FLAGS_MU                mem(&m_core->flags.mu)
+#define FLAGS_MD                mem(&m_core->flags.md)
+
+#define PRP                     mem(&m_core->prp)
+#define PWP                     mem(&m_core->pwp)
+#define RPC                     mem(&m_core->rpc)
+#define LPC                     mem(&m_core->lpc)
+
+#define AZ_CALC_REQUIRED        ((desc->regreq[1] & 0x1) || desc->flags & OPFLAG_IN_DELAY_SLOT)
+#define AN_CALC_REQUIRED        ((desc->regreq[1] & 0x2) || desc->flags & OPFLAG_IN_DELAY_SLOT)
+#define AV_CALC_REQUIRED        ((desc->regreq[1] & 0x4) || desc->flags & OPFLAG_IN_DELAY_SLOT)
+#define AU_CALC_REQUIRED        ((desc->regreq[1] & 0x8) || desc->flags & OPFLAG_IN_DELAY_SLOT)
+#define AD_CALC_REQUIRED        ((desc->regreq[1] & 0x10) || desc->flags & OPFLAG_IN_DELAY_SLOT)
+#define ZC_CALC_REQUIRED        ((desc->regreq[1] & 0x20) || desc->flags & OPFLAG_IN_DELAY_SLOT)
+#define IL_CALC_REQUIRED        ((desc->regreq[1] & 0x40) || desc->flags & OPFLAG_IN_DELAY_SLOT)
+#define NR_CALC_REQUIRED        ((desc->regreq[1] & 0x80) || desc->flags & OPFLAG_IN_DELAY_SLOT)
+#define ZD_CALC_REQUIRED        ((desc->regreq[1] & 0x100) || desc->flags & OPFLAG_IN_DELAY_SLOT)
+#define MN_CALC_REQUIRED        ((desc->regreq[1] & 0x200) || desc->flags & OPFLAG_IN_DELAY_SLOT)
+#define MZ_CALC_REQUIRED        ((desc->regreq[1] & 0x400) || desc->flags & OPFLAG_IN_DELAY_SLOT)
+#define MV_CALC_REQUIRED        ((desc->regreq[1] & 0x800) || desc->flags & OPFLAG_IN_DELAY_SLOT)
+#define MU_CALC_REQUIRED        ((desc->regreq[1] & 0x1000) || desc->flags & OPFLAG_IN_DELAY_SLOT)
+#define MD_CALC_REQUIRED        ((desc->regreq[1] & 0x2000) || desc->flags & OPFLAG_IN_DELAY_SLOT)
+
+#define FIFOIN_RPOS             mem(&m_core->fifoin.rpos)
+#define FIFOIN_WPOS             mem(&m_core->fifoin.wpos)
+#define FIFOIN_NUM              mem(&m_core->fifoin.num)
+#define FIFOOUT0_RPOS           mem(&m_core->fifoout0.rpos)
+#define FIFOOUT0_WPOS           mem(&m_core->fifoout0.wpos)
+#define FIFOOUT0_NUM            mem(&m_core->fifoout0.num)
+#define FIFOOUT1_RPOS           mem(&m_core->fifoout1.rpos)
+#define FIFOOUT1_WPOS           mem(&m_core->fifoout1.wpos)
+#define FIFOOUT1_NUM            mem(&m_core->fifoout1.num)
+
+
+inline void mb86235_device::alloc_handle(drcuml_state *drcuml, code_handle **handleptr, const char *name)
+{
+	if (*handleptr == nullptr)
+		*handleptr = drcuml->handle_alloc(name);
+}
+
+
+
+static void cfunc_unimplemented(void *param)
+{
+	mb86235_device *cpu = (mb86235_device *)param;
+	cpu->unimplemented_op();
+}
+
+static void cfunc_unimplemented_alu(void *param)
+{
+	mb86235_device *cpu = (mb86235_device *)param;
+	cpu->unimplemented_alu();
+}
+
+static void cfunc_unimplemented_control(void *param)
+{
+	mb86235_device *cpu = (mb86235_device *)param;
+	cpu->unimplemented_control();
+}
+
+static void cfunc_unimplemented_double_xfer1(void *param)
+{
+	mb86235_device *cpu = (mb86235_device *)param;
+	cpu->unimplemented_double_xfer1();
+}
+
+static void cfunc_unimplemented_double_xfer2(void *param)
+{
+	mb86235_device *cpu = (mb86235_device *)param;
+	cpu->unimplemented_double_xfer2();
+}
+
+static void cfunc_pcs_overflow(void *param)
+{
+	mb86235_device *cpu = (mb86235_device *)param;
+	cpu->pcs_overflow();
+}
+
+static void cfunc_pcs_underflow(void *param)
+{
+	mb86235_device *cpu = (mb86235_device *)param;
+	cpu->pcs_underflow();
+}
+
+
+
+void mb86235_device::unimplemented_op()
+{
+	uint64_t op = m_core->arg64;
+	printf("MB86235: PC=%08X: Unimplemented op %04X%08X\n", m_core->pc, (uint32_t)(op >> 32), (uint32_t)(op));
+	fatalerror("MB86235: PC=%08X: Unimplemented op %04X%08X\n", m_core->pc, (uint32_t)(op >> 32), (uint32_t)(op));
+}
+
+void mb86235_device::unimplemented_alu()
+{
+	uint32_t op = m_core->arg0;
+	printf("MB86235: PC=%08X: Unimplemented alu %02X\n", m_core->pc, op);
+	fatalerror("MB86235: PC=%08X: Unimplemented alu %02X\n", m_core->pc, op);
+}
+
+void mb86235_device::unimplemented_control()
+{
+	uint32_t cop = m_core->arg0;
+	printf("MB86235: PC=%08X: Unimplemented control %02X\n", m_core->pc, cop);
+	fatalerror("MB86235: PC=%08X: Unimplemented control %02X\n", m_core->pc, cop);
+}
+
+void mb86235_device::unimplemented_double_xfer1()
+{
+	uint64_t op = m_core->arg64;
+	printf("MB86235: PC=%08X: Unimplemented double xfer1 %04X%08X\n", m_core->pc, (uint32_t)(op >> 32), (uint32_t)(op));
+	fatalerror("MB86235: PC=%08X: Unimplemented double xfer1 %04X%08X\n", m_core->pc, (uint32_t)(op >> 32), (uint32_t)(op));
+}
+
+void mb86235_device::unimplemented_double_xfer2()
+{
+	uint64_t op = m_core->arg64;
+	printf("MB86235: PC=%08X: Unimplemented double xfer2 %04X%08X\n", m_core->pc, (uint32_t)(op >> 32), (uint32_t)(op));
+	fatalerror("MB86235: PC=%08X: Unimplemented double xfer2 %04X%08X\n", m_core->pc, (uint32_t)(op >> 32), (uint32_t)(op));
+}
+
+void mb86235_device::pcs_overflow()
+{
+	printf("MB86235: PC=%08X: PCS overflow\n", m_core->pc);
+	fatalerror("MB86235: PC=%08X: PCS overflow\n", m_core->pc);
+}
+
+void mb86235_device::pcs_underflow()
+{
+	printf("MB86235: PC=%08X: PCS underflow\n", m_core->pc);
+	fatalerror("MB86235: PC=%08X: PCS underflow\n", m_core->pc);
+}
+
+
+
+
+/*-------------------------------------------------
+load_fast_iregs - load any fast integer
+registers
+-------------------------------------------------*/
+
+inline void mb86235_device::load_fast_iregs(drcuml_block *block)
+{
+	int regnum;
+
+	for (regnum = 0; regnum < ARRAY_LENGTH(m_regmap); regnum++)
+	{
+		if (m_regmap[regnum].is_int_register())
+		{
+		}
+	}
+}
+
+
+/*-------------------------------------------------
+save_fast_iregs - save any fast integer
+registers
+-------------------------------------------------*/
+
+void mb86235_device::save_fast_iregs(drcuml_block *block)
+{
+	int regnum;
+
+	for (regnum = 0; regnum < ARRAY_LENGTH(m_regmap); regnum++)
+	{
+		if (m_regmap[regnum].is_int_register())
+		{
+		}
+	}
+}
+
+
+
+
+void mb86235_device::run_drc()
+{
+	drcuml_state *drcuml = m_drcuml.get();
+	int execute_result;
+
+	/* execute */
+	do
+	{
+		execute_result = drcuml->execute(*m_entry);
+
+		/* if we need to recompile, do it */
+		if (execute_result == EXECUTE_MISSING_CODE)
+		{
+			compile_block(m_core->pc);
+		}
+		else if (execute_result == EXECUTE_UNMAPPED_CODE)
+		{
+			fatalerror("Attempted to execute unmapped code at PC=%08X\n", m_core->pc);
+		}
+		else if (execute_result == EXECUTE_RESET_CACHE)
+		{
+			flush_cache();
+		}
+	} while (execute_result != EXECUTE_OUT_OF_CYCLES);
+}
+
+void mb86235_device::compile_block(offs_t pc)
+{
+	compiler_state compiler = { 0 };
+
+	const opcode_desc *seqhead, *seqlast;
+	const opcode_desc *desclist;
+	bool override = false;
+
+	drcuml_block *block;
+
+	desclist = m_drcfe->describe_code(pc);
+
+	bool succeeded = false;
+	while (!succeeded)
+	{
+		try
+		{
+			block = m_drcuml->begin_block(4096);
+
+			for (seqhead = desclist; seqhead != nullptr; seqhead = seqlast->next())
+			{
+				const opcode_desc *curdesc;
+				uint32_t nextpc;
+
+				/* determine the last instruction in this sequence */
+				for (seqlast = seqhead; seqlast != nullptr; seqlast = seqlast->next())
+					if (seqlast->flags & OPFLAG_END_SEQUENCE)
+						break;
+				assert(seqlast != nullptr);
+
+				/* if we don't have a hash for this mode/pc, or if we are overriding all, add one */
+				if (override || m_drcuml->hash_exists(0, seqhead->pc))
+					UML_HASH(block, 0, seqhead->pc);                                        // hash    mode,pc
+
+																							/* if we already have a hash, and this is the first sequence, assume that we */
+																							/* are recompiling due to being out of sync and allow future overrides */
+				else if (seqhead == desclist)
+				{
+					override = true;
+					UML_HASH(block, 0, seqhead->pc);                                        // hash    mode,pc
+				}
+
+				/* otherwise, redispatch to that fixed PC and skip the rest of the processing */
+				else
+				{
+					UML_LABEL(block, seqhead->pc | 0x80000000);                             // label   seqhead->pc
+					UML_HASHJMP(block, 0, seqhead->pc, *m_nocode);                          // hashjmp <0>,seqhead->pc,nocode
+					continue;
+				}
+
+				/* label this instruction, if it may be jumped to locally */
+				if (seqhead->flags & OPFLAG_IS_BRANCH_TARGET)
+					UML_LABEL(block, seqhead->pc | 0x80000000);                             // label   seqhead->pc
+
+																							/* iterate over instructions in the sequence and compile them */
+				for (curdesc = seqhead; curdesc != seqlast->next(); curdesc = curdesc->next())
+					generate_sequence_instruction(block, &compiler, curdesc);
+
+				/* if we need to return to the start, do it */
+				if (seqlast->flags & OPFLAG_RETURN_TO_START)
+					nextpc = pc;
+				/* otherwise we just go to the next instruction */
+				else
+					nextpc = seqlast->pc + (seqlast->skipslots + 1);
+
+				/* count off cycles and go there */
+				generate_update_cycles(block, &compiler, nextpc, true);                     // <subtract cycles>
+
+				if (seqlast->next() == nullptr || seqlast->next()->pc != nextpc)
+					UML_HASHJMP(block, 0, nextpc, *m_nocode);                               // hashjmp <mode>,nextpc,nocode
+			}
+
+			block->end();
+			succeeded = true;
+		}
+		catch (drcuml_block::abort_compilation &)
+		{
+			flush_cache();
+		}
+	}
+}
+
+
+
+void mb86235_device::static_generate_entry_point()
+{
+	//code_label skip = 1;
+	drcuml_block *block;
+
+	/* begin generating */
+	block = m_drcuml->begin_block(20);
+
+	/* forward references */
+	alloc_handle(m_drcuml.get(), &m_nocode, "nocode");
+
+	alloc_handle(m_drcuml.get(), &m_entry, "entry");
+	UML_HANDLE(block, *m_entry);                                                            // handle  entry
+
+	load_fast_iregs(block);                                                                 // <load fastregs>
+
+	/* generate a hash jump via the current mode and PC */
+	UML_HASHJMP(block, 0, mem(&m_core->pc), *m_nocode);   // hashjmp <mode>,<pc>,nocode
+
+	block->end();
+}
+
+
+void mb86235_device::static_generate_nocode_handler()
+{
+	drcuml_block *block;
+
+	/* begin generating */
+	block = m_drcuml->begin_block(10);
+
+	/* generate a hash jump via the current mode and PC */
+	alloc_handle(m_drcuml.get(), &m_nocode, "nocode");
+	UML_HANDLE(block, *m_nocode);                                                           // handle  nocode
+	UML_GETEXP(block, I0);                                                                  // getexp  i0
+	UML_MOV(block, mem(&m_core->pc), I0);                                                   // mov     [pc],i0
+	save_fast_iregs(block);                                                                 // <save fastregs>
+	UML_EXIT(block, EXECUTE_MISSING_CODE);                                                  // exit    EXECUTE_MISSING_CODE
+
+	block->end();
+}
+
+void mb86235_device::static_generate_out_of_cycles()
+{
+	drcuml_block *block;
+
+	/* begin generating */
+	block = m_drcuml->begin_block(10);
+
+	/* generate a hash jump via the current mode and PC */
+	alloc_handle(m_drcuml.get(), &m_out_of_cycles, "out_of_cycles");
+	UML_HANDLE(block, *m_out_of_cycles);                                                    // handle  out_of_cycles
+	UML_GETEXP(block, I0);                                                                  // getexp  i0
+	UML_MOV(block, mem(&m_core->pc), I0);                                                   // mov     <pc>,i0
+	save_fast_iregs(block);                                                                 // <save fastregs>
+	UML_EXIT(block, EXECUTE_OUT_OF_CYCLES);                                                 // exit    EXECUTE_OUT_OF_CYCLES
+
+	block->end();
+}
+
+void mb86235_device::static_generate_fifo()
+{
+	drcuml_block *block;
+
+	// clear fifo in
+	block = m_drcuml->begin_block(20);
+
+	alloc_handle(m_drcuml.get(), &m_clear_fifo_in, "clear_fifo_in");
+	UML_HANDLE(block, *m_clear_fifo_in);
+	UML_MOV(block, FIFOIN_NUM, 0);
+	UML_MOV(block, FIFOIN_RPOS, 0);
+	UML_MOV(block, FIFOIN_WPOS, 0);
+	UML_RET(block);
+
+	block->end();
+
+	// clear fifo out0
+	block = m_drcuml->begin_block(20);
+
+	alloc_handle(m_drcuml.get(), &m_clear_fifo_out0, "clear_fifo_out0");
+	UML_HANDLE(block, *m_clear_fifo_out0);
+	UML_MOV(block, FIFOOUT0_NUM, 0);
+	UML_MOV(block, FIFOOUT0_RPOS, 0);
+	UML_MOV(block, FIFOOUT0_WPOS, 0);
+	UML_RET(block);
+
+	block->end();
+
+	// clear fifo out1
+	block = m_drcuml->begin_block(20);
+
+	alloc_handle(m_drcuml.get(), &m_clear_fifo_out1, "clear_fifo_out1");
+	UML_HANDLE(block, *m_clear_fifo_out1);
+	UML_MOV(block, FIFOOUT1_NUM, 0);
+	UML_MOV(block, FIFOOUT1_RPOS, 0);
+	UML_MOV(block, FIFOOUT1_WPOS, 0);
+	UML_RET(block);
+
+	block->end();
+
+	// read fifo in
+	// I0 = return value
+	block = m_drcuml->begin_block(32);
+	alloc_handle(m_drcuml.get(), &m_read_fifo_in, "read_fifo_in");
+	UML_HANDLE(block, *m_read_fifo_in);
+	UML_MOV(block, I1, FIFOIN_RPOS);
+	UML_LOAD(block, I0, m_core->fifoin.data, I1, SIZE_QWORD, SCALE_x8);
+	UML_ADD(block, I1, I1, 1);
+	UML_AND(block, I1, I1, FIFOIN_SIZE-1);
+	UML_MOV(block, FIFOIN_RPOS, I1);
+	UML_SUB(block, FIFOIN_NUM, FIFOIN_NUM, 1);
+	UML_RET(block);
+
+	block->end();
+
+	// write fifo out0
+	// I0 = input value
+	block = m_drcuml->begin_block(32);
+	alloc_handle(m_drcuml.get(), &m_write_fifo_out0, "write_fifo_out0");
+	UML_HANDLE(block, *m_write_fifo_out0);
+	UML_MOV(block, I1, FIFOOUT0_WPOS);
+	UML_STORE(block, m_core->fifoout0.data, I1, I0, SIZE_QWORD, SCALE_x8);
+	UML_ADD(block, I1, I1, 1);
+	UML_AND(block, I1, I1, FIFOOUT0_SIZE - 1);
+	UML_MOV(block, FIFOOUT0_WPOS, I1);
+	UML_ADD(block, FIFOOUT0_NUM, FIFOOUT0_NUM, 1);
+	UML_RET(block);
+
+	block->end();
+
+	// write fifo out1
+	block = m_drcuml->begin_block(32);
+	alloc_handle(m_drcuml.get(), &m_write_fifo_out1, "write_fifo_out1");
+	UML_HANDLE(block, *m_write_fifo_out1);
+	// TODO
+	UML_RET(block);
+
+	block->end();
+}
+
+void mb86235_device::static_generate_memory_accessors()
+{
+	drcuml_block *block;
+	code_label label = 1;
+
+	// A-Bus read handler
+	// I0 = address
+	// I1 = return data
+	// I2 = trashed
+	block = m_drcuml->begin_block(128);
+
+	alloc_handle(m_drcuml.get(), &m_read_abus, "read_abus");
+	UML_HANDLE(block, *m_read_abus);
+	UML_CMP(block, I0, 0x400);
+	UML_JMPc(block, COND_GE, label);
+	// internal A-RAM
+	UML_SHL(block, I0, I0, 2);
+	UML_READ(block, I1, I0, SIZE_DWORD, SPACE_DATA);
+	UML_RET(block);
+	// external
+	UML_LABEL(block, label++);
+	UML_AND(block, I0, I0, 0x3fff);
+	UML_AND(block, I2, mem(&m_core->eb), ~0x3fff);
+	UML_OR(block, I0, I0, I2);
+	UML_SHL(block, I0, I0, 2);
+	UML_READ(block, I1, I0, SIZE_DWORD, SPACE_DATA);
+	UML_RET(block);
+
+	block->end();
+
+	// A-Bus write handler
+	// I0 = address
+	// I1 = data
+	// I2 = trashed
+	block = m_drcuml->begin_block(128);
+
+	alloc_handle(m_drcuml.get(), &m_write_abus, "write_abus");
+	UML_HANDLE(block, *m_write_abus);
+	UML_CMP(block, I0, 0x400);
+	UML_JMPc(block, COND_GE, label);
+	// internal A-RAM
+	UML_SHL(block, I0, I0, 2);
+	UML_WRITE(block, I0, I1, SIZE_DWORD, SPACE_DATA);
+	UML_RET(block);
+	// external
+	UML_LABEL(block, label++);
+	UML_AND(block, I0, I0, 0x3fff);
+	UML_AND(block, I2, mem(&m_core->eb), ~0x3fff);
+	UML_OR(block, I0, I0, I2);
+	UML_SHL(block, I0, I0, 2);
+	UML_WRITE(block, I0, I1, SIZE_DWORD, SPACE_DATA);
+	UML_RET(block);
+
+	block->end();
+}
+
+
+void mb86235_device::flush_cache()
+{
+	/* empty the transient cache contents */
+	m_drcuml->reset();
+
+	try
+	{
+		// generate the entry point and out-of-cycles handlers
+		static_generate_entry_point();
+		static_generate_nocode_handler();
+		static_generate_out_of_cycles();
+
+		// generate utility functions
+		static_generate_fifo();
+
+		// generate exception handlers
+
+		// generate memory accessors
+		static_generate_memory_accessors();
+	}
+	catch (drcuml_block::abort_compilation &)
+	{
+		fatalerror("Error generating MB86235 static handlers\n");
+	}
+}
+
+
+
+void mb86235_device::generate_sequence_instruction(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+	/* add an entry for the log */
+	//  if (m_drcuml->logging() && !(desc->flags & OPFLAG_VIRTUAL_NOOP))
+	//      log_add_disasm_comment(block, desc->pc, desc->opptr.l[0]);
+
+	/* set the PC map variable */
+	UML_MAPVAR(block, MAPVAR_PC, desc->pc);                                                 // mapvar  PC,desc->pc
+
+																							/* accumulate total cycles */
+	compiler->cycles += desc->cycles;
+
+	/* update the icount map variable */
+	UML_MAPVAR(block, MAPVAR_CYCLES, compiler->cycles);                                     // mapvar  CYCLES,compiler->cycles
+
+																							/* if we are debugging, call the debugger */
+	if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+	{
+		UML_MOV(block, mem(&m_core->pc), desc->pc);                                         // mov     [pc],desc->pc
+		save_fast_iregs(block);                                                             // <save fastregs>
+		UML_DEBUG(block, desc->pc);                                                         // debug   desc->pc
+	}
+
+	/* if we hit an unmapped address, fatal error */
+	if (desc->flags & OPFLAG_COMPILER_UNMAPPED)
+	{
+		UML_MOV(block, mem(&m_core->pc), desc->pc);                                         // mov     [pc],desc->pc
+		save_fast_iregs(block);                                                             // <save fastregs>
+		UML_EXIT(block, EXECUTE_UNMAPPED_CODE);                                             // exit    EXECUTE_UNMAPPED_CODE
+	}
+
+	/* if this is an invalid opcode, generate the exception now */
+	//  if (desc->flags & OPFLAG_INVALID_OPCODE)
+	//      UML_EXH(block, *m_exception[EXCEPTION_PROGRAM], 0x80000);                           // exh    exception_program,0x80000
+
+	/* unless this is a virtual no-op, it's a regular instruction */
+	if (!(desc->flags & OPFLAG_VIRTUAL_NOOP))
+	{
+		/* compile the instruction */
+		if (!generate_opcode(block, compiler, desc))
+		{
+			UML_MOV(block, mem(&m_core->pc), desc->pc);                                     // mov     [pc],desc->pc
+			UML_DMOV(block, mem(&m_core->arg64), desc->opptr.q[0]);                         // dmov    [arg64],*desc->opptr.q
+			UML_CALLC(block, cfunc_unimplemented, this);                                    // callc   cfunc_unimplemented,ppc
+		}
+	}
+}
+
+void mb86235_device::generate_update_cycles(drcuml_block *block, compiler_state *compiler, uml::parameter param, bool allow_exception)
+{
+	/* account for cycles */
+	if (compiler->cycles > 0)
+	{
+		UML_SUB(block, mem(&m_core->icount), mem(&m_core->icount), MAPVAR_CYCLES);          // sub     icount,icount,cycles
+		UML_MAPVAR(block, MAPVAR_CYCLES, 0);                                                // mapvar  cycles,0
+		if (allow_exception)
+			UML_EXHc(block, COND_S, *m_out_of_cycles, param);                               // exh     out_of_cycles,nextpc
+	}
+	compiler->cycles = 0;
+}
+
+
+void mb86235_device::generate_ea(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int md, int arx, int ary, int disp)
+{
+	// Calculates EA into register I0
+
+	switch (md)
+	{
+		case 0x0:   // @ARx
+			UML_MOV(block, I0, AR(arx));
+			break;
+		case 0x1:   // @ARx++
+			UML_MOV(block, I0, AR(arx));
+			UML_ADD(block, AR(arx), AR(arx), 1);
+			break;
+		case 0x4:   // @ARx+ARy
+			UML_ADD(block, I0, AR(arx), AR(ary));
+			break;
+		case 0xa:   // @ARx+disp12
+			UML_ADD(block, I0, AR(arx), disp);
+			break;
+
+		default:
+			fatalerror("generate_ea: md = %02X, PC = %08X", md, desc->pc);
+			break;
+	}
+}
+
+
+
+void mb86235_device::generate_reg_read(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int reg, uml::parameter dst)
+{
+	switch (reg)
+	{
+		case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+			// AA0-7
+			UML_MOV(block, dst, AA(reg & 7));
+			break;
+
+		case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+			// AR0-7
+			UML_MOV(block, dst, AR(reg & 7));
+			break;
+
+		case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+			// AB0-7
+			UML_MOV(block, dst, AB(reg & 7));
+			break;
+
+		case 0x30:  // PR
+			UML_LOAD(block, dst, m_core->pr, PRP, SIZE_DWORD, SCALE_x4);
+			break;
+
+		case 0x31:  // FI
+			UML_CALLH(block, *m_read_fifo_in);
+			UML_MOV(block, dst, I0);
+			break;
+
+		default:
+			fatalerror("generate_reg_read: unimplemented register %02X at %08X", reg, desc->pc);
+			break;
+	}
+}
+
+
+void mb86235_device::generate_reg_write(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int reg, uml::parameter src)
+{
+	switch (reg)
+	{
+		case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+			// MA0-7
+			UML_MOV(block, MA(reg & 7), src);
+			break;
+
+		case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+			// AA0-7
+			UML_MOV(block, AA(reg & 7), src);
+			break;
+
+		case 0x10:      // EB
+			UML_MOV(block, mem(&m_core->eb), src);
+			break;
+
+		case 0x13:      // EO
+			UML_MOV(block, mem(&m_core->eo), src);
+			break;
+
+		case 0x14:      // SP
+			UML_MOV(block, mem(&m_core->sp), src);
+			break;
+
+		case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+			// AR0-7
+			UML_MOV(block, AR(reg & 7), src);
+			break;
+
+		case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
+			// MB0-7
+			UML_MOV(block, MB(reg & 7), src);
+			break;
+
+		case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+			// AB0-7
+			UML_MOV(block, AB(reg & 7), src);
+			break;
+
+		case 0x30:      // PR
+			UML_STORE(block, m_core->pr, PWP, src, SIZE_DWORD, SCALE_x4);
+			break;
+
+		case 0x32:      // FO0
+			UML_MOV(block, I0, src);
+			UML_CALLH(block, *m_write_fifo_out0);
+			break;
+
+		case 0x34:      // PDR
+			UML_MOV(block, mem(&m_core->pdr), src);
+			break;
+
+		case 0x35:      // DDR
+			UML_MOV(block, mem(&m_core->ddr), src);
+			break;
+
+		case 0x36:      // PRP
+			UML_MOV(block, PRP, src);
+			break;
+
+		case 0x37:      // PWP
+			UML_MOV(block, PWP, src);
+			break;
+
+		default:
+			fatalerror("generate_reg_write: unimplemented register %02X at %08X", reg, desc->pc);
+			break;
+	}
+}
+
+bool mb86235_device::has_register_clash(const opcode_desc *desc, int outreg)
+{
+	switch (outreg)
+	{
+		case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+			// MA0-7
+			if (desc->regin[0] & (1 << (16 + (outreg & 7)))) return true;
+			break;
+		case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+			// MB0-7
+			if (desc->regin[0] & (1 << (24 + (outreg & 7)))) return true;
+			break;
+		case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+			// AA0-7
+			if (desc->regin[0] & (1 << (outreg & 7))) return true;
+			break;
+		case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+			// AB0-7
+			if (desc->regin[0] & (1 << (8 + (outreg & 7)))) return true;
+			break;
+	}
+	return false;
+}
+
+bool mb86235_device::aluop_has_result(int aluop)
+{
+	switch (aluop)
+	{
+		case 0x04:      // FCMP
+		case 0x07:      // NOP
+		case 0x14:      // CMP
+			return false;
+
+		default:
+			break;
+	}
+	return true;
+}
+
+
+
+bool mb86235_device::generate_opcode(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+	uint64_t opcode = desc->opptr.q[0];
+
+	bool fifoin_check = false;
+	bool fifoout0_check = false;
+	bool fifoout1_check = false;
+
+	// enable fifo in check if this opcode or the delay slot reads from FIFO
+	if (desc->userflags & OP_USERFLAG_FIFOIN)
+		fifoin_check = true;
+	if (desc->delayslots > 0)
+	{
+		if (desc->delay.first()->userflags & OP_USERFLAG_FIFOIN)
+			fifoin_check = true;
+	}
+
+	// enable fifoout0 check if this opcode or the delay slot writes to FIFO0
+	if (desc->userflags & OP_USERFLAG_FIFOOUT0)
+		fifoout0_check = true;
+	if (desc->delayslots > 0)
+	{
+		if (desc->delay.first()->userflags & OP_USERFLAG_FIFOOUT0)
+			fifoout0_check = true;
+	}
+
+	// enable fifoout1 check if this opcode or the delay slot writes to FIFO1
+	if (desc->userflags & OP_USERFLAG_FIFOOUT1)
+		fifoout1_check = true;
+	if (desc->delayslots > 0)
+	{
+		if (desc->delay.first()->userflags & OP_USERFLAG_FIFOOUT1)
+			fifoout1_check = true;
+	}
+
+	// insert FIFO IN check if needed
+	if (fifoin_check)
+	{
+		code_label not_empty = compiler->labelnum++;
+		UML_CMP(block, FIFOIN_NUM, 0);
+		UML_JMPc(block, COND_G, not_empty);
+
+		UML_MOV(block, mem(&m_core->icount), 0);
+		UML_EXH(block, *m_out_of_cycles, desc->pc);
+
+		UML_LABEL(block, not_empty);
+	}
+
+	// insert FIFO OUT0 check if needed
+	if (fifoout0_check)
+	{
+		code_label not_full = compiler->labelnum++;
+		UML_CMP(block, FIFOOUT0_NUM, FIFOOUT0_SIZE - 1);
+		UML_JMPc(block, COND_L, not_full);
+
+		UML_MOV(block, mem(&m_core->icount), 0);
+		UML_EXH(block, *m_out_of_cycles, desc->pc);
+
+		UML_LABEL(block, not_full);
+	}
+
+	// insert FIFO OUT1 check if needed
+	if (fifoout1_check)
+	{
+		code_label not_full = compiler->labelnum++;
+		UML_CMP(block, FIFOOUT1_NUM, FIFOOUT1_SIZE - 1);
+		UML_JMPc(block, COND_L, not_full);
+
+		UML_MOV(block, mem(&m_core->icount), 0);
+		UML_EXH(block, *m_out_of_cycles, desc->pc);
+
+		UML_LABEL(block, not_full);
+	}
+
+
+	switch ((opcode >> 61) & 7)
+	{
+		case 0:     // ALU / MUL / double transfer (type 1)
+		{
+			bool alu_temp = has_register_clash(desc, (opcode >> 42) & 0x1f) && aluop_has_result((opcode >> 56) & 0x1f);
+			bool mul_temp = has_register_clash(desc, (opcode >> 27) & 0x1f);
+			generate_alu(block, compiler, desc, (opcode >> 42) & 0x7ffff, alu_temp);
+			generate_mul(block, compiler, desc, (opcode >> 27) & 0x7fff, mul_temp);
+			generate_double_xfer1(block, compiler, desc);
+			if (alu_temp) UML_MOV(block, get_alu_output((opcode >> 42) & 0x1f), mem(&m_core->alutemp));
+			if (mul_temp) UML_MOV(block, get_alu_output((opcode >> 27) & 0x1f), mem(&m_core->multemp));
+			break;
+		}
+		case 1:     // ALU / MUL / transfer (type 1)
+		{
+			bool alu_temp = has_register_clash(desc, (opcode >> 42) & 0x1f) && aluop_has_result((opcode >> 56) & 0x1f);
+			bool mul_temp = has_register_clash(desc, (opcode >> 27) & 0x1f);
+			generate_alu(block, compiler, desc, (opcode >> 42) & 0x7ffff, alu_temp);
+			generate_mul(block, compiler, desc, (opcode >> 27) & 0x7fff, mul_temp);
+			generate_xfer1(block, compiler, desc);
+			if (alu_temp) UML_MOV(block, get_alu_output((opcode >> 42) & 0x1f), mem(&m_core->alutemp));
+			if (mul_temp) UML_MOV(block, get_alu_output((opcode >> 27) & 0x1f), mem(&m_core->multemp));
+			break;
+		}
+		case 2:     // ALU / MUL / control
+		{
+			generate_pre_control(block, compiler, desc);
+			generate_alu(block, compiler, desc, (opcode >> 42) & 0x7ffff, false);
+			generate_mul(block, compiler, desc, (opcode >> 27) & 0x7fff, false);
+			generate_control(block, compiler, desc);
+			break;
+		}
+		case 4:     // ALU or MUL / double transfer (type 2)
+		{
+			bool comp_temp;
+			if (opcode & ((uint64_t)(1) << 41))
+			{
+				comp_temp = has_register_clash(desc, (opcode >> 42) & 0x1f) && aluop_has_result((opcode >> 56) & 0x1f);
+				generate_alu(block, compiler, desc, (opcode >> 42) & 0x7ffff, comp_temp);
+			}
+			else
+			{
+				comp_temp = has_register_clash(desc, (opcode >> 42) & 0x1f);
+				generate_mul(block, compiler, desc, (opcode >> 42) & 0x7fff, comp_temp);
+			}
+			generate_double_xfer2(block, compiler, desc);
+			if (comp_temp)
+			{
+				if (opcode & ((uint64_t)(1) << 41))
+					UML_MOV(block, get_alu_output((opcode >> 42) & 0x1f), mem(&m_core->alutemp));
+				else
+					UML_MOV(block, get_alu_output((opcode >> 42) & 0x1f), mem(&m_core->multemp));
+			}
+			break;
+		}
+		case 5:     // ALU or MUL / transfer (type 2)
+		{
+			bool comp_temp;
+			if (opcode & ((uint64_t)(1) << 41))
+			{
+				comp_temp = has_register_clash(desc, (opcode >> 42) & 0x1f) && aluop_has_result((opcode >> 56) & 0x1f);
+				generate_alu(block, compiler, desc, (opcode >> 42) & 0x7ffff, comp_temp);
+			}
+			else
+			{
+				comp_temp = has_register_clash(desc, (opcode >> 42) & 0x1f);
+				generate_mul(block, compiler, desc, (opcode >> 42) & 0x7fff, comp_temp);
+			}
+			generate_xfer2(block, compiler, desc);
+			if (comp_temp)
+			{
+				if (opcode & ((uint64_t)(1) << 41))
+					UML_MOV(block, get_alu_output((opcode >> 42) & 0x1f), mem(&m_core->alutemp));
+				else
+					UML_MOV(block, get_alu_output((opcode >> 42) & 0x1f), mem(&m_core->multemp));
+			}
+			break;
+		}
+		case 6:     // ALU or MUL / control
+		{
+			generate_pre_control(block, compiler, desc);
+			if (opcode & ((uint64_t)(1) << 41))
+				generate_alu(block, compiler, desc, (opcode >> 42) & 0x7ffff, false);
+			else
+				generate_mul(block, compiler, desc, (opcode >> 42) & 0x7fff, false);
+			generate_control(block, compiler, desc);
+			break;
+		}
+		case 7:     // transfer (type 3)
+		{
+			generate_xfer3(block, compiler, desc);
+			break;
+		}
+
+		default:
+			return false;
+	}
+
+	// update PR and PW if needed
+	if ((desc->userflags & OP_USERFLAG_PR_MASK) != 0)
+	{
+		switch ((desc->userflags & OP_USERFLAG_PR_MASK) >> 8)
+		{
+			case 1:     // PR++
+				UML_ADD(block, PRP, PRP, 1);
+				UML_CMP(block, PRP, 24);
+				UML_MOVc(block, COND_GE, PRP, 0);
+				break;
+			case 2:     // PR--
+				UML_SUB(block, PRP, PRP, 1);
+				UML_CMP(block, PRP, 0);
+				UML_MOVc(block, COND_L, PRP, 23);
+				break;
+			case 3:     // PR#0
+				UML_MOV(block, PRP, 0);
+				break;
+		}
+	}
+
+	if ((desc->userflags & OP_USERFLAG_PW_MASK) != 0)
+	{
+		switch ((desc->userflags & OP_USERFLAG_PW_MASK) >> 10)
+		{
+			case 1:     // PW++
+				UML_ADD(block, PWP, PWP, 1);
+				UML_CMP(block, PWP, 24);
+				UML_MOVc(block, COND_GE, PWP, 0);
+				break;
+			case 2:     // PW--
+				UML_SUB(block, PWP, PWP, 1);
+				UML_CMP(block, PWP, 0);
+				UML_MOVc(block, COND_L, PWP, 23);
+				break;
+			case 3:     // PW#0
+				UML_MOV(block, PWP, 0);
+				break;
+		}
+	}
+
+	// handle repeat
+	if (desc->userflags & OP_USERFLAG_REPEATED_OP)
+	{
+		code_label no_repeat = compiler->labelnum++;
+		UML_SUB(block, RPC, RPC, 1);
+		UML_CMP(block, RPC, 0);
+		UML_JMPc(block, COND_LE, no_repeat);
+
+		generate_update_cycles(block, compiler, desc->pc, true);
+		if (desc->flags & OPFLAG_INTRABLOCK_BRANCH)
+			UML_JMP(block, desc->pc | 0x80000000);
+		else
+			UML_HASHJMP(block, 0, desc->pc, *m_nocode);
+
+		UML_LABEL(block, no_repeat);
+	}
+
+	return true;
+}
+
+
+
+void mb86235_device::generate_alumul_input(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int reg, uml::parameter dst, bool fp, bool mul)
+{
+	switch (reg)
+	{
+		case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+			if (mul)
+				UML_MOV(block, dst, MA(reg & 7));
+			else
+				UML_MOV(block, dst, AA(reg & 7));
+			break;
+
+		case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+			if (mul)
+				UML_MOV(block, dst, MB(reg & 7));
+			else
+				UML_MOV(block, dst, AB(reg & 7));
+			break;
+
+		case 0x10:  // PR
+		case 0x11:  // PR++
+		case 0x12:  // PR--
+		case 0x13:  // PR#0
+			UML_LOAD(block, dst, m_core->pr, PRP, SIZE_DWORD, SCALE_x4);
+			break;
+
+		case 0x18:  // 0 / -1.0E+0
+			if (fp)
+				UML_MOV(block, dst, 0xbf800000);
+			else
+				UML_MOV(block, dst, 0);
+			break;
+
+		case 0x19:  // 1 / 0.0E+0
+			if (fp)
+				UML_MOV(block, dst, 0);
+			else
+				UML_MOV(block, dst, 1);
+			break;
+
+		case 0x1a:  // -1 / 0.5+0
+			if (fp)
+				UML_MOV(block, dst, 0x3f000000);
+			else
+				UML_MOV(block, dst, -1);
+			break;
+
+		case 0x1b:  // 1.0E+0
+			UML_MOV(block, dst, 0x3f800000);
+			break;
+
+		case 0x1c:  // 1.5E+0
+			UML_MOV(block, dst, 0x3fc00000);
+			break;
+
+		case 0x1d:  // 2.0E+0
+			UML_MOV(block, dst, 0x40000000);
+			break;
+
+		case 0x1e:  // 3.0E+0
+			UML_MOV(block, dst, 0x40400000);
+			break;
+
+		case 0x1f:  // 5.0E+0
+			UML_MOV(block, dst, 0x40a00000);
+			break;
+
+		default:
+			fatalerror("generate_alu_input: invalid register %02X", reg);
+	}
+}
+
+uml::parameter mb86235_device::get_alu_output(int reg)
+{
+	switch (reg)
+	{
+		case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+			return MA(reg & 7);
+		case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+			return MB(reg & 7);
+		case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+			return AA(reg & 7);
+		case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+			return AB(reg & 7);
+	}
+	return uml::parameter(0);
+}
+
+uml::parameter mb86235_device::get_alu1_input(int reg)
+{
+	switch (reg)
+	{
+		case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+			return AA(reg & 7);
+
+		case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+			return AB(reg & 7);
+	}
+	return uml::parameter(0);
+}
+
+uml::parameter mb86235_device::get_mul1_input(int reg)
+{
+	switch (reg)
+	{
+		case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+			return MA(reg & 7);
+
+		case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+			return MB(reg & 7);
+	}
+	return uml::parameter(0);
+}
+
+
+
+void mb86235_device::generate_alu(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int aluop, bool alutemp)
+{
+	int i1 = (aluop >> 10) & 0xf;
+	int i2 = (aluop >> 5) & 0x1f;
+	int io = aluop & 0x1f;
+	int op = (aluop >> 14) & 0x1f;
+
+	switch (op)
+	{
+		case 0x00:      // FADD
+			generate_alumul_input(block, compiler, desc, i2, I0, true, false);
+			UML_FSCOPYI(block, F0, I0);
+			UML_FSCOPYI(block, F1, get_alu1_input(i1));
+			UML_FSADD(block, F0, F0, F1);
+			UML_ICOPYFS(block, alutemp ? mem(&m_core->alutemp) : get_alu_output(io), F0);
+			if (AN_CALC_REQUIRED || AZ_CALC_REQUIRED)
+				UML_FSCMP(block, F0, mem(&m_core->fp0));
+			if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, FLAGS_AN);
+			if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, FLAGS_AZ);
+			// TODO: AV flag
+			// TODO: AU flag
+			// TODO: AD flag
+			break;
+
+		case 0x02:      // FSUB
+			generate_alumul_input(block, compiler, desc, i2, I0, true, false);
+			UML_FSCOPYI(block, F0, I0);
+			UML_FSCOPYI(block, F1, get_alu1_input(i1));
+			UML_FSSUB(block, F0, F0, F1);
+			UML_ICOPYFS(block, alutemp ? mem(&m_core->alutemp) : get_alu_output(io), F0);
+			if (AN_CALC_REQUIRED || AZ_CALC_REQUIRED)
+				UML_FSCMP(block, F0, mem(&m_core->fp0));
+			if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, FLAGS_AN);
+			if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, FLAGS_AZ);
+			// TODO: AV flag
+			// TODO: AU flag
+			// TODO: AD flag
+			break;
+
+		case 0x04:      // FCMP
+			generate_alumul_input(block, compiler, desc, i2, I0, true, false);
+			UML_FSCOPYI(block, F0, I0);
+			UML_FSCOPYI(block, F1, get_alu1_input(i1));
+			UML_FSCMP(block, F0, F1);
+			if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, FLAGS_AN);
+			if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, FLAGS_AZ);
+			// TODO: AV flag
+			// TODO: AU flag
+			// TODO: AD flag
+			break;
+
+		case 0x05:      // FABS
+			UML_AND(block, alutemp ? mem(&m_core->alutemp) : get_alu_output(io), get_alu1_input(i1), 0x7fffffff);
+			if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, FLAGS_AZ);
+			if (AN_CALC_REQUIRED) UML_MOV(block, FLAGS_AN, 0);
+			// TODO: AD flag
+			break;
+
+		case 0x06:      // FABC
+			generate_alumul_input(block, compiler, desc, i2, I0, true, false);
+			UML_AND(block, I0, I0, 0x7fffffff);
+			UML_AND(block, I1, get_alu1_input(i1), 0x7fffffff);
+			UML_FSCOPYI(block, F0, I0);
+			UML_FSCOPYI(block, F1, I1);
+			UML_FSCMP(block, F0, F1);
+			if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, FLAGS_AN);
+			if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, FLAGS_AZ);
+			if (AU_CALC_REQUIRED) UML_MOV(block, FLAGS_AU, 1);
+			// TODO: AD flag
+			break;
+
+		case 0x07:      // NOP
+			break;
+
+		case 0x0d:      // CIF
+			generate_alumul_input(block, compiler, desc, i1, I1, true, false);
+			UML_FSFRINT(block, F0, I1, SIZE_DWORD);
+			if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED)
+				UML_CMP(block, I1, 0);
+			if (AN_CALC_REQUIRED) UML_SETc(block, COND_L, FLAGS_AN);
+			if (AZ_CALC_REQUIRED) UML_SETc(block, COND_E, FLAGS_AZ);
+			UML_ICOPYFS(block, alutemp ? mem(&m_core->alutemp) : get_alu_output(io), F0);
+			break;
+
+		case 0x0e:      // CFI
+		{
+			code_label truncate = compiler->labelnum++;
+			code_label end = compiler->labelnum++;
+			UML_FSCOPYI(block, F0, get_alu1_input(i1));
+			UML_TEST(block, mem(&m_core->mod), 0x80);
+			UML_JMPc(block, COND_Z, truncate);
+			UML_FSTOINT(block, I0, F0, SIZE_DWORD, ROUND_ROUND);
+			UML_JMP(block, end);
+			UML_LABEL(block, truncate);
+			UML_FSTOINT(block, I0, F0, SIZE_DWORD, ROUND_TRUNC);
+			UML_LABEL(block, end);
+
+			UML_CMP(block, I0, 0xff800000);
+			UML_MOVc(block, COND_L, I0, 0xff800000);
+			if (AV_CALC_REQUIRED) UML_MOVc(block, COND_L, FLAGS_AV, 1);
+			UML_CMP(block, I0, 0x007fffff);
+			UML_MOVc(block, COND_G, I0, 0x007fffff);
+			if (AV_CALC_REQUIRED) UML_MOVc(block, COND_G, FLAGS_AV, 1);
+			if (AN_CALC_REQUIRED || AZ_CALC_REQUIRED)
+				UML_CMP(block, I0, 0);
+			if (AN_CALC_REQUIRED) UML_SETc(block, COND_L, FLAGS_AN);
+			if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, FLAGS_AZ);
+			UML_MOV(block, alutemp ? mem(&m_core->alutemp) : get_alu_output(io), I0);
+			break;
+		}
+
+		case 0x10:      // ADD
+			generate_alumul_input(block, compiler, desc, i2, I1, false, false);
+			UML_ADD(block, I0, I1, get_alu1_input(i1));
+			if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, FLAGS_AZ);
+			if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, FLAGS_AN);
+			UML_CMP(block, I0, 0xff800000);
+			UML_MOVc(block, COND_L, I0, 0xff800000);
+			if (AV_CALC_REQUIRED) UML_MOVc(block, COND_L, FLAGS_AV, 1);
+			UML_CMP(block, I0, 0x007fffff);
+			UML_MOVc(block, COND_G, I0, 0x007fffff);
+			if (AV_CALC_REQUIRED) UML_MOVc(block, COND_G, FLAGS_AV, 1);
+			UML_MOV(block, alutemp ? mem(&m_core->alutemp) : get_alu_output(io), I0);
+			break;
+
+		case 0x12:      // SUB
+			generate_alumul_input(block, compiler, desc, i2, I1, false, false);
+			UML_SUB(block, I0, I1, get_alu1_input(i1));
+			if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, FLAGS_AZ);
+			if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, FLAGS_AN);
+			UML_CMP(block, I0, 0xff800000);
+			UML_MOVc(block, COND_L, I0, 0xff800000);
+			if (AV_CALC_REQUIRED) UML_MOVc(block, COND_L, FLAGS_AV, 1);
+			UML_CMP(block, I0, 0x007fffff);
+			UML_MOVc(block, COND_G, I0, 0x007fffff);
+			if (AV_CALC_REQUIRED) UML_MOVc(block, COND_G, FLAGS_AV, 1);
+			UML_MOV(block, alutemp ? mem(&m_core->alutemp) : get_alu_output(io), I0);
+			break;
+
+		case 0x14:      // CMP
+			generate_alumul_input(block, compiler, desc, i2, I1, false, false);
+			UML_SUB(block, I0, I1, get_alu1_input(i1));
+			if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, FLAGS_AZ);
+			if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, FLAGS_AN);
+			if (AV_CALC_REQUIRED)
+			{
+				UML_CMP(block, I0, 0xff800000);
+				UML_MOVc(block, COND_L, FLAGS_AV, 1);
+				UML_CMP(block, I0, 0x007fffff);
+				UML_MOVc(block, COND_G, FLAGS_AV, 1);
+			}
+			break;
+
+		case 0x16:      // ATR
+			UML_MOV(block, alutemp ? mem(&m_core->alutemp) : get_alu_output(io), get_alu1_input(i1));
+			break;
+
+		case 0x18:      // AND
+			generate_alumul_input(block, compiler, desc, i2, I0, false, false);
+			UML_AND(block, alutemp ? mem(&m_core->alutemp) : get_alu_output(io), I0, get_alu1_input(i1));
+			if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, FLAGS_AN);
+			if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, FLAGS_AZ);
+			if (AV_CALC_REQUIRED) UML_MOV(block, FLAGS_AV, 0);
+			if (AU_CALC_REQUIRED) UML_MOV(block, FLAGS_AU, 0);
+			break;
+
+		case 0x1c:      // LSR
+			generate_alumul_input(block, compiler, desc, i1, I0, false, false);
+			UML_SHR(block, I0, I0, i2);
+			if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED)
+				UML_CMP(block, I0, 0);
+			if (AN_CALC_REQUIRED) UML_SETc(block, COND_L, FLAGS_AN);
+			if (AZ_CALC_REQUIRED) UML_SETc(block, COND_E, FLAGS_AZ);
+			if (AV_CALC_REQUIRED) UML_MOV(block, FLAGS_AV, 0);
+			if (AU_CALC_REQUIRED) UML_MOV(block, FLAGS_AU, 0);
+			UML_MOV(block, alutemp ? mem(&m_core->alutemp) : get_alu_output(io), I0);
+			break;
+
+		case 0x1d:      // LSL
+			generate_alumul_input(block, compiler, desc, i1, I0, false, false);
+			UML_SHL(block, I0, I0, i2);
+			if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED)
+				UML_CMP(block, I0, 0);
+			if (AN_CALC_REQUIRED) UML_SETc(block, COND_L, FLAGS_AN);
+			if (AZ_CALC_REQUIRED) UML_SETc(block, COND_E, FLAGS_AZ);
+			if (AV_CALC_REQUIRED) UML_MOV(block, FLAGS_AV, 0);
+			if (AU_CALC_REQUIRED) UML_MOV(block, FLAGS_AU, 0);
+			UML_MOV(block, alutemp ? mem(&m_core->alutemp) : get_alu_output(io), I0);
+			break;
+
+		default:
+			UML_MOV(block, mem(&m_core->pc), desc->pc);
+			UML_MOV(block, mem(&m_core->arg0), op);
+			UML_CALLC(block, cfunc_unimplemented_alu, this);
+			break;
+	}
+}
+
+void mb86235_device::generate_mul(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int mulop, bool multemp)
+{
+	int i1 = (mulop >> 10) & 0xf;
+	int i2 = (mulop >> 5) & 0x1f;
+	int io = mulop & 0x1f;
+	int m = mulop & 0x4000;
+
+	if (m)
+	{
+		// FMUL
+		generate_alumul_input(block, compiler, desc, i2, I1, true, true);
+		UML_FSCOPYI(block, F1, I1);
+		UML_FSCOPYI(block, F0, get_mul1_input(i1));
+		UML_FSMUL(block, F1, F0, F1);
+		if (MZ_CALC_REQUIRED || MN_CALC_REQUIRED)
+			UML_FSCMP(block, F1, mem(&m_core->fp0));
+		if (MZ_CALC_REQUIRED) UML_SETc(block, COND_E, FLAGS_MZ);
+		if (MN_CALC_REQUIRED) UML_SETc(block, COND_C, FLAGS_MN);
+		// TODO: MV flag
+		// TODO: MU flag
+		// TODO: MD flag
+		UML_ICOPYFS(block, multemp ? mem(&m_core->multemp) : get_alu_output(io), F1);
+	}
+	else
+	{
+		// MUL
+		generate_alumul_input(block, compiler, desc, i2, I1, false, true);
+		UML_MULS(block, I0, I0, I1, get_mul1_input(i1));
+		if (MZ_CALC_REQUIRED) UML_SETc(block, COND_Z, FLAGS_MZ);
+		if (MN_CALC_REQUIRED) UML_SETc(block, COND_S, FLAGS_MN);
+		UML_CMP(block, I0, 0xff800000);
+		UML_MOVc(block, COND_L, I0, 0xff800000);
+		if (MV_CALC_REQUIRED) UML_MOVc(block, COND_L, FLAGS_MV, 1);
+		UML_CMP(block, I0, 0x007fffff);
+		UML_MOVc(block, COND_G, I0, 0x007fffff);
+		if (MV_CALC_REQUIRED) UML_MOVc(block, COND_G, FLAGS_MV, 1);
+		UML_MOV(block, multemp ? mem(&m_core->multemp) : get_alu_output(io), I0);
+	}
+}
+
+
+void mb86235_device::generate_branch(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+	// I0 = target pc for dynamic branches
+
+	compiler_state compiler_temp = *compiler;
+
+	// save branch target
+	if (desc->targetpc == BRANCH_TARGET_DYNAMIC)
+	{
+		UML_MOV(block, mem(&m_core->jmpdest), I0);                                     // mov     [jmpdest],i0
+	}
+
+	// compile delay slots
+	generate_sequence_instruction(block, &compiler_temp, desc->delay.first());
+
+	// update cycles and hash jump
+	if (desc->targetpc != BRANCH_TARGET_DYNAMIC)
+	{
+		generate_update_cycles(block, &compiler_temp, desc->targetpc, true);
+		if (desc->flags & OPFLAG_INTRABLOCK_BRANCH)
+			UML_JMP(block, desc->targetpc | 0x80000000);                                // jmp      targetpc | 0x80000000
+		else
+			UML_HASHJMP(block, 0, desc->targetpc, *m_nocode);                           // hashjmp  0,targetpc,nocode
+	}
+	else
+	{
+		generate_update_cycles(block, &compiler_temp, mem(&m_core->jmpdest), true);
+		UML_HASHJMP(block, 0, mem(&m_core->jmpdest), *m_nocode);                        // hashjmp  0,jmpdest,nocode
+	}
+
+	// update compiler label
+	compiler->labelnum = compiler_temp.labelnum;
+
+	/* reset the mapvar to the current cycles and account for skipped slots */
+	compiler->cycles += desc->skipslots;
+	UML_MAPVAR(block, MAPVAR_CYCLES, compiler->cycles);                                 // mapvar  CYCLES,compiler->cycles
+}
+
+
+void mb86235_device::generate_branch_target(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int type, int ef2)
+{
+	// Calculates dynamic targets into I0
+
+	switch (type)
+	{
+		case 0x0: break;
+		case 0x1: break;
+		case 0x2:           // ARx
+		{
+			int reg = (ef2 >> 6) & 7;
+			UML_MOV(block, I0, AR(reg));
+			break;
+		}
+		case 0x4:           // Axx
+		{
+			int reg = (ef2 >> 6) & 7;
+			if (ef2 & 0x400)
+				UML_MOV(block, I0, AB(reg));
+			else
+				UML_MOV(block, I0, AA(reg));
+			break;
+		}
+		default:
+			fatalerror("generate_branch_target: type %02X at %08X", type, desc->pc);
+			break;
+	}
+}
+
+
+void mb86235_device::generate_condition(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int cc, bool n, uml::code_label skip_label, bool condtemp)
+{
+	switch (cc)
+	{
+		case 0x00:      // MN
+			UML_CMP(block, condtemp ? mem(&m_core->condtemp) : FLAGS_MN, 0);
+			UML_JMPc(block, n ? COND_NE : COND_E, skip_label);
+			break;
+		case 0x01:      // MZ
+			UML_CMP(block, condtemp ? mem(&m_core->condtemp) : FLAGS_MZ, 0);
+			UML_JMPc(block, n ? COND_NE : COND_E, skip_label);
+			break;
+		case 0x02:      // MV
+			UML_CMP(block, condtemp ? mem(&m_core->condtemp) : FLAGS_MV, 0);
+			UML_JMPc(block, n ? COND_NE : COND_E, skip_label);
+			break;
+		case 0x03:      // MU
+			UML_CMP(block, condtemp ? mem(&m_core->condtemp) : FLAGS_MU, 0);
+			UML_JMPc(block, n ? COND_NE : COND_E, skip_label);
+			break;
+		case 0x04:      // ZD
+			UML_CMP(block, condtemp ? mem(&m_core->condtemp) : FLAGS_ZD, 0);
+			UML_JMPc(block, n ? COND_NE : COND_E, skip_label);
+			break;
+		case 0x05:      // NR
+			UML_CMP(block, condtemp ? mem(&m_core->condtemp) : FLAGS_NR, 0);
+			UML_JMPc(block, n ? COND_NE : COND_E, skip_label);
+			break;
+		case 0x06:      // IL
+			UML_CMP(block, condtemp ? mem(&m_core->condtemp) : FLAGS_IL, 0);
+			UML_JMPc(block, n ? COND_NE : COND_E, skip_label);
+			break;
+		case 0x07:      // ZC
+			UML_CMP(block, condtemp ? mem(&m_core->condtemp) : FLAGS_ZC, 0);
+			UML_JMPc(block, n ? COND_NE : COND_E, skip_label);
+			break;
+		case 0x08:      // AN
+			UML_CMP(block, condtemp ? mem(&m_core->condtemp) : FLAGS_AN, 0);
+			UML_JMPc(block, n ? COND_NE : COND_E, skip_label);
+			break;
+		case 0x09:      // AZ
+			UML_CMP(block, condtemp ? mem(&m_core->condtemp) : FLAGS_AZ, 0);
+			UML_JMPc(block, n ? COND_NE : COND_E, skip_label);
+			break;
+		case 0x0a:      // AV
+			UML_CMP(block, condtemp ? mem(&m_core->condtemp) : FLAGS_AV, 0);
+			UML_JMPc(block, n ? COND_NE : COND_E, skip_label);
+			break;
+		case 0x0b:      // AU
+			UML_CMP(block, condtemp ? mem(&m_core->condtemp) : FLAGS_AU, 0);
+			UML_JMPc(block, n ? COND_NE : COND_E, skip_label);
+			break;
+		case 0x0c:      // MD
+			UML_CMP(block, condtemp ? mem(&m_core->condtemp) : FLAGS_MD, 0);
+			UML_JMPc(block, n ? COND_NE : COND_E, skip_label);
+			break;
+		case 0x0d:      // AD
+			UML_CMP(block, condtemp ? mem(&m_core->condtemp) : FLAGS_AD, 0);
+			UML_JMPc(block, n ? COND_NE : COND_E, skip_label);
+			break;
+		default:
+			fatalerror("generate_condition: unimplemented cc %02X at %08X", cc, desc->pc);
+			break;
+	}
+}
+
+
+void mb86235_device::generate_control(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+	uint64_t op = desc->opptr.q[0];
+	int ef1 = (op >> 16) & 0x3f;
+	int ef2 = op & 0xffff;
+	int cop = (op >> 22) & 0x1f;
+//  int rel12 = (op & 0x800) ? (0xfffff000 | (op & 0xfff)) : (op & 0xfff);
+
+	switch (cop)
+	{
+		case 0x00:      // NOP
+			break;
+
+		case 0x03:      //
+			if (ef1 == 1)   // CLRFI
+				UML_CALLH(block, *m_clear_fifo_in);
+			else if (ef1 == 2)  // CLRFO
+			{
+				UML_CALLH(block, *m_clear_fifo_out0);
+				UML_CALLH(block, *m_clear_fifo_out1);
+			}
+			else if (ef1 == 3)  // CLRF
+			{
+				UML_CALLH(block, *m_clear_fifo_in);
+				UML_CALLH(block, *m_clear_fifo_out0);
+				UML_CALLH(block, *m_clear_fifo_out1);
+			}
+			break;
+
+		case 0x08:      // SETM #imm16
+			UML_MOV(block, mem(&m_core->mod), ef2);
+			break;
+
+		case 0x10:      // DBcc
+		{
+			code_label skip_label = compiler->labelnum++;
+
+			generate_branch_target(block, compiler, desc, (op >> 12) & 0xf, ef2);
+			generate_condition(block, compiler, desc, ef1, false, skip_label, true);
+			generate_branch(block, compiler, desc);
+			UML_LABEL(block, skip_label);
+			break;
+		}
+
+		case 0x11:      // DBNcc
+		{
+			code_label skip_label = compiler->labelnum++;
+
+			generate_branch_target(block, compiler, desc, (op >> 12) & 0xf, ef2);
+			generate_condition(block, compiler, desc, ef1, true, skip_label, true);
+			generate_branch(block, compiler, desc);
+			UML_LABEL(block, skip_label);
+			break;
+		}
+
+		case 0x12:      // DJMP
+		{
+			generate_branch_target(block, compiler, desc, (op >> 12) & 0xf, ef2);
+			generate_branch(block, compiler, desc);
+			break;
+		}
+
+		case 0x1a:      // DCALL
+		{
+			// push PC
+			code_label no_overflow = compiler->labelnum++;
+			UML_CMP(block, mem(&m_core->pcs_ptr), 4);
+			UML_JMPc(block, COND_L, no_overflow);
+			UML_MOV(block, mem(&m_core->pc), desc->pc);
+			UML_CALLC(block, cfunc_pcs_overflow, this);
+
+			UML_LABEL(block, no_overflow);
+			UML_STORE(block, m_core->pcs, mem(&m_core->pcs_ptr), desc->pc + 2, SIZE_DWORD, SCALE_x4);
+			UML_ADD(block, mem(&m_core->pcs_ptr), mem(&m_core->pcs_ptr), 1);
+
+			generate_branch_target(block, compiler, desc, (op >> 12) & 0xf, ef2);
+			generate_branch(block, compiler, desc);
+			break;
+		}
+
+		case 0x1b:      // DRET
+		{
+			// pop PC
+			code_label no_underflow = compiler->labelnum++;
+			UML_CMP(block, mem(&m_core->pcs_ptr), 0);
+			UML_JMPc(block, COND_G, no_underflow);
+			UML_MOV(block, mem(&m_core->pc), desc->pc);
+			UML_CALLC(block, cfunc_pcs_underflow, this);
+
+			UML_LABEL(block, no_underflow);
+			UML_SUB(block, mem(&m_core->pcs_ptr), mem(&m_core->pcs_ptr), 1);
+			UML_LOAD(block, I0, m_core->pcs, mem(&m_core->pcs_ptr), SIZE_DWORD, SCALE_x4);
+
+			generate_branch(block, compiler, desc);
+			break;
+		}
+
+		default:
+			UML_MOV(block, mem(&m_core->pc), desc->pc);
+			UML_MOV(block, mem(&m_core->arg0), cop);
+			UML_CALLC(block, cfunc_unimplemented_control, this);
+			break;
+	}
+}
+
+void mb86235_device::generate_xfer1(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+	uint64_t opcode = desc->opptr.q[0];
+
+	int dr = (opcode >> 12) & 0x7f;
+	int sr = (opcode >> 19) & 0x7f;
+	int md = opcode & 0xf;
+	int ary = (opcode >> 4) & 7;
+	int disp5 = (opcode >> 7) & 0x1f;
+	int trm = (opcode >> 26) & 1;
+//  int dir = (opcode >> 25) & 1;
+
+	if (trm == 0)
+	{
+		if (sr == 0x58)
+		{
+			// MOV1 #imm12, DR
+			generate_reg_write(block, compiler, desc, dr & 0x3f, uml::parameter(opcode & 0xfff));
+		}
+		else
+		{
+			if ((sr & 0x40) == 0)
+			{
+				generate_reg_read(block, compiler, desc, sr & 0x3f, I1);
+			}
+			else
+			{
+				generate_ea(block, compiler, desc, md, sr & 7, ary, disp5);
+				if (sr & 0x20)  // RAM-B
+				{
+					UML_SHL(block, I0, I0, 2);
+					UML_READ(block, I1, I0, SIZE_DWORD, SPACE_IO);
+				}
+				else // RAM-A
+				{
+					UML_CALLH(block, *m_read_abus);
+				}
+			}
+
+			if ((dr & 0x40) == 0)
+			{
+				generate_reg_write(block, compiler, desc, dr & 0x3f, I1);
+			}
+			else
+			{
+				generate_ea(block, compiler, desc, md, dr & 7, ary, disp5);
+				if (dr & 0x20)  // RAM-B
+				{
+					UML_SHL(block, I0, I0, 2);
+					UML_WRITE(block, I0, I1, SIZE_DWORD, SPACE_IO);
+				}
+				else // RAM-A
+				{
+					UML_CALLH(block, *m_write_abus);
+				}
+			}
+		}
+	}
+	else
+	{
+		// external transfer
+		fatalerror("generate_xfer1 MOV1 at %08X (%08X%08X)", desc->pc, (uint32_t)(opcode >> 32), (uint32_t)(opcode));
+	}
+}
+
+void mb86235_device::generate_double_xfer1(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+	UML_MOV(block, mem(&m_core->pc), desc->pc);
+	UML_DMOV(block, mem(&m_core->arg64), desc->opptr.q[0]);
+	UML_CALLC(block, cfunc_unimplemented_double_xfer1, this);
+}
+
+void mb86235_device::generate_xfer2(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+	uint64_t opcode = desc->opptr.q[0];
+
+	int op = (opcode >> 39) & 3;
+	int trm = (opcode >> 38) & 1;
+	int dir = (opcode >> 37) & 1;
+	int sr = (opcode >> 31) & 0x7f;
+	int dr = (opcode >> 24) & 0x7f;
+	int ary = (opcode >> 4) & 7;
+	int md = opcode & 0xf;
+
+	int disp14 = (opcode >> 7) & 0x3fff;
+	if (disp14 & 0x2000) disp14 |= 0xffffc000;
+
+	if (op == 0)    // MOV2
+	{
+		if (trm == 0)
+		{
+			if (sr == 0x58)
+			{
+				// MOV2 #imm24, DR
+				generate_reg_write(block, compiler, desc, dr & 0x3f, uml::parameter(opcode & 0xffffff));
+			}
+			else
+			{
+				if ((sr & 0x40) == 0)
+				{
+					generate_reg_read(block, compiler, desc, sr & 0x3f, I1);
+				}
+				else
+				{
+					generate_ea(block, compiler, desc, md, sr & 7, ary, disp14);
+					if (sr & 0x20)  // RAM-B
+					{
+						UML_SHL(block, I0, I0, 2);
+						UML_READ(block, I1, I0, SIZE_DWORD, SPACE_IO);
+					}
+					else // RAM-A
+					{
+						UML_CALLH(block, *m_read_abus);
+					}
+				}
+
+				if ((dr & 0x40) == 0)
+				{
+					generate_reg_write(block, compiler, desc, dr & 0x3f, I1);
+				}
+				else
+				{
+					generate_ea(block, compiler, desc, md, dr & 7, ary, disp14);
+					if (dr & 0x20)  // RAM-B
+					{
+						UML_SHL(block, I0, I0, 2);
+						UML_WRITE(block, I0, I1, SIZE_DWORD, SPACE_IO);
+					}
+					else // RAM-A
+					{
+						UML_CALLH(block, *m_write_abus);
+					}
+				}
+			}
+		}
+		else
+		{
+			// external transfer
+			if (dir == 0)
+			{
+				generate_reg_read(block, compiler, desc, dr & 0x3f, I0);
+				UML_ADD(block, I1, mem(&m_core->eb), mem(&m_core->eo));
+				UML_ADD(block, I1, I1, disp14);
+				UML_SHL(block, I1, I1, 2);
+				UML_WRITE(block, I1, I0, SIZE_DWORD, SPACE_DATA);
+			}
+			else
+			{
+				UML_ADD(block, I1, mem(&m_core->eb), mem(&m_core->eo));
+				UML_ADD(block, I1, I1, disp14);
+				UML_SHL(block, I1, I1, 2);
+				UML_READ(block, I0, I1, SIZE_DWORD, SPACE_DATA);
+				generate_reg_write(block, compiler, desc, dr & 0x3f, I0);
+			}
+
+			// update EO
+			UML_ADD(block, mem(&m_core->eo), mem(&m_core->eo), disp14);
+		}
+	}
+	else if (op == 2)   // MOV4
+	{
+		fatalerror("generate_xfer2 MOV4 at %08X (%08X%08X)", desc->pc, (uint32_t)(opcode >> 32), (uint32_t)(opcode));
+	}
+}
+
+void mb86235_device::generate_double_xfer2(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+	UML_MOV(block, mem(&m_core->pc), desc->pc);
+	UML_DMOV(block, mem(&m_core->arg64), desc->opptr.q[0]);
+	UML_CALLC(block, cfunc_unimplemented_double_xfer2, this);
+}
+
+void mb86235_device::generate_xfer3(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+	uint64_t opcode = desc->opptr.q[0];
+
+	uint32_t imm = (uint32_t)(opcode >> 27);
+	int dr = (opcode >> 19) & 0x7f;
+	int ary = (opcode >> 4) & 7;
+	int md = opcode & 0xf;
+
+	int disp = (opcode >> 7) & 0xfff;
+	if (disp & 0x800) disp |= 0xfffff800;
+
+	switch (dr >> 5)
+	{
+		case 0:
+		case 1:     // reg
+			generate_reg_write(block, compiler, desc, dr & 0x3f, uml::parameter(imm));
+			break;
+
+		case 2:     // RAM-A
+			generate_ea(block, compiler, desc, md, dr & 7, ary, disp);
+			UML_MOV(block, I1, imm);
+			UML_CALLH(block, *m_write_abus);
+			break;
+
+		case 3:     // RAM-B
+			generate_ea(block, compiler, desc, md, dr & 7, ary, disp);
+			UML_SHL(block, I0, I0, 2);
+			UML_WRITE(block, I0, imm, SIZE_DWORD, SPACE_IO);
+			break;
+	}
+}
+
+
+void mb86235_device::generate_pre_control(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+	uint64_t op = desc->opptr.q[0];
+	int ef1 = (op >> 16) & 0x3f;
+	int ef2 = op & 0xffff;
+	int cop = (op >> 22) & 0x1f;
+
+	switch (cop)
+	{
+		case 0x10:      // DBcc
+		case 0x11:      // DBNcc
+		case 0x18:      // DCcc
+		case 0x19:      // DCNcc
+			switch (ef1)
+			{
+				case 0x00:  UML_MOV(block, mem(&m_core->condtemp), FLAGS_MN); break;        // MN
+				case 0x01:  UML_MOV(block, mem(&m_core->condtemp), FLAGS_MZ); break;        // MZ
+				case 0x02:  UML_MOV(block, mem(&m_core->condtemp), FLAGS_MV); break;        // MV
+				case 0x03:  UML_MOV(block, mem(&m_core->condtemp), FLAGS_MU); break;        // MU
+				case 0x04:  UML_MOV(block, mem(&m_core->condtemp), FLAGS_ZD); break;        // ZD
+				case 0x05:  UML_MOV(block, mem(&m_core->condtemp), FLAGS_NR); break;        // NR
+				case 0x06:  UML_MOV(block, mem(&m_core->condtemp), FLAGS_IL); break;        // IL
+				case 0x07:  UML_MOV(block, mem(&m_core->condtemp), FLAGS_ZC); break;        // ZC
+				case 0x08:  UML_MOV(block, mem(&m_core->condtemp), FLAGS_AN); break;        // AN
+				case 0x09:  UML_MOV(block, mem(&m_core->condtemp), FLAGS_AZ); break;        // AZ
+				case 0x0a:  UML_MOV(block, mem(&m_core->condtemp), FLAGS_AV); break;        // AV
+				case 0x0b:  UML_MOV(block, mem(&m_core->condtemp), FLAGS_AU); break;        // AU
+				case 0x0c:  UML_MOV(block, mem(&m_core->condtemp), FLAGS_MD); break;        // MD
+				case 0x0d:  UML_MOV(block, mem(&m_core->condtemp), FLAGS_AD); break;        // AD
+				default:
+					fatalerror("generate_pre_control: unimplemented cc %02X at %08X", ef1, desc->pc);
+					break;
+			}
+			break;
+
+		case 0x14:      // DBBC ARx:y, rel12
+			// TODO: copy ARx
+			UML_MOV(block, mem(&m_core->condtemp), AR((ef2 >> 13) & 7));
+			break;
+
+		case 0x15:      // DBBS ARx:y, rel12
+			// TODO: copy ARx
+			UML_MOV(block, mem(&m_core->condtemp), AR((ef2 >> 13) & 7));
+			break;
+
+		default:
+			break;
+	}
+}
diff --git a/src/devices/cpu/mb86235/mb86235fe.cpp b/src/devices/cpu/mb86235/mb86235fe.cpp
new file mode 100644
index 0000000..f55fb09
--- /dev/null
+++ b/src/devices/cpu/mb86235/mb86235fe.cpp
@@ -0,0 +1,922 @@
+// license:BSD-3-Clause
+// copyright-holders:Ville Linde
+
+/******************************************************************************
+
+    Front-end for MB86235 recompiler
+
+******************************************************************************/
+
+#include "emu.h"
+#include "mb86235fe.h"
+
+
+#define AA_USED(desc,x)             do { (desc).regin[0] |= 1 << (x); } while(0)
+#define AA_MODIFIED(desc,x)         do { (desc).regout[0] |= 1 << (x); } while(0)
+#define AB_USED(desc,x)             do { (desc).regin[0] |= 1 << (8+(x)); } while(0)
+#define AB_MODIFIED(desc,x)         do { (desc).regout[0] |= 1 << (8+(x)); } while(0)
+#define MA_USED(desc,x)             do { (desc).regin[0] |= 1 << (16+(x)); } while(0)
+#define MA_MODIFIED(desc,x)         do { (desc).regout[0] |= 1 << (16+(x)); } while(0)
+#define MB_USED(desc,x)             do { (desc).regin[0] |= 1 << (24+(x)); } while(0)
+#define MB_MODIFIED(desc,x)         do { (desc).regout[0] |= 1 << (24+(x)); } while(0)
+#define AR_USED(desc,x)             do { (desc).regin[1] |= 1 << (24+(x)); } while(0)
+#define AR_MODIFIED(desc,x)         do { (desc).regout[1] |= 1 << (24+(x)); } while(0)
+
+#define AZ_USED(desc)               do { (desc).regin[1] |= 1 << 0; } while (0)
+#define AZ_MODIFIED(desc)           do { (desc).regout[1] |= 1 << 0; } while (0)
+#define AN_USED(desc)               do { (desc).regin[1] |= 1 << 1; } while (0)
+#define AN_MODIFIED(desc)           do { (desc).regout[1] |= 1 << 1; } while (0)
+#define AV_USED(desc)               do { (desc).regin[1] |= 1 << 2; } while (0)
+#define AV_MODIFIED(desc)           do { (desc).regout[1] |= 1 << 2; } while (0)
+#define AU_USED(desc)               do { (desc).regin[1] |= 1 << 3; } while (0)
+#define AU_MODIFIED(desc)           do { (desc).regout[1] |= 1 << 3; } while (0)
+#define AD_USED(desc)               do { (desc).regin[1] |= 1 << 4; } while (0)
+#define AD_MODIFIED(desc)           do { (desc).regout[1] |= 1 << 4; } while (0)
+#define ZC_USED(desc)               do { (desc).regin[1] |= 1 << 5; } while (0)
+#define ZC_MODIFIED(desc)           do { (desc).regout[1] |= 1 << 5; } while (0)
+#define IL_USED(desc)               do { (desc).regin[1] |= 1 << 6; } while (0)
+#define IL_MODIFIED(desc)           do { (desc).regout[1] |= 1 << 6; } while (0)
+#define NR_USED(desc)               do { (desc).regin[1] |= 1 << 7; } while (0)
+#define NR_MODIFIED(desc)           do { (desc).regout[1] |= 1 << 7; } while (0)
+#define ZD_USED(desc)               do { (desc).regin[1] |= 1 << 8; } while (0)
+#define ZD_MODIFIED(desc)           do { (desc).regout[1] |= 1 << 8; } while (0)
+#define MN_USED(desc)               do { (desc).regin[1] |= 1 << 9; } while (0)
+#define MN_MODIFIED(desc)           do { (desc).regout[1] |= 1 << 9; } while (0)
+#define MZ_USED(desc)               do { (desc).regin[1] |= 1 << 10; } while (0)
+#define MZ_MODIFIED(desc)           do { (desc).regout[1] |= 1 << 10; } while (0)
+#define MV_USED(desc)               do { (desc).regin[1] |= 1 << 11; } while (0)
+#define MV_MODIFIED(desc)           do { (desc).regout[1] |= 1 << 11; } while (0)
+#define MU_USED(desc)               do { (desc).regin[1] |= 1 << 12; } while (0)
+#define MU_MODIFIED(desc)           do { (desc).regout[1] |= 1 << 12; } while (0)
+#define MD_USED(desc)               do { (desc).regin[1] |= 1 << 13; } while (0)
+#define MD_MODIFIED(desc)           do { (desc).regout[1] |= 1 << 13; } while (0)
+
+
+mb86235_frontend::mb86235_frontend(mb86235_device *core, uint32_t window_start, uint32_t window_end, uint32_t max_sequence)
+	: drc_frontend(*core, window_start, window_end, max_sequence),
+	m_core(core)
+{
+}
+
+
+bool mb86235_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
+{
+	uint64_t opcode = desc.opptr.q[0] = m_core->m_direct->read_qword(desc.pc * 8, 0);
+
+	desc.length = 1;
+	desc.cycles = 1;
+
+	// repeatable instruction needs an entry point
+	if (prev != nullptr)
+	{
+		if (prev->userflags & OP_USERFLAG_REPEAT)
+		{
+			desc.flags |= OPFLAG_IS_BRANCH_TARGET;
+			desc.userflags |= OP_USERFLAG_REPEATED_OP;
+		}
+	}
+
+	switch ((opcode >> 61) & 7)
+	{
+		case 0:     // ALU / MUL / double transfer (type 1)
+			describe_alu(desc, (opcode >> 42) & 0x7ffff);
+			describe_mul(desc, (opcode >> 27) & 0x7fff);
+			describe_double_xfer1(desc);
+			break;
+		case 1:     // ALU / MUL / transfer (type 1)
+			describe_alu(desc, (opcode >> 42) & 0x7ffff);
+			describe_mul(desc, (opcode >> 27) & 0x7fff);
+			describe_xfer1(desc);
+			break;
+		case 2:     // ALU / MUL / control
+			describe_alu(desc, (opcode >> 42) & 0x7ffff);
+			describe_mul(desc, (opcode >> 27) & 0x7fff);
+			describe_control(desc);
+			break;
+		case 4:     // ALU or MUL / double transfer (type 2)
+			if (opcode & ((uint64_t)(1) << 41))
+				describe_alu(desc, (opcode >> 42) & 0x7ffff);
+			else
+				describe_mul(desc, (opcode >> 42) & 0x7fff);
+			describe_double_xfer2(desc);
+			break;
+		case 5:     // ALU or MUL / transfer (type 2)
+			if (opcode & ((uint64_t)(1) << 41))
+				describe_alu(desc, (opcode >> 42) & 0x7ffff);
+			else
+				describe_mul(desc, (opcode >> 42) & 0x7fff);
+			describe_xfer2(desc);
+			break;
+		case 6:     // ALU or MUL / control
+			if (opcode & ((uint64_t)(1) << 41))
+				describe_alu(desc, (opcode >> 42) & 0x7ffff);
+			else
+				describe_mul(desc, (opcode >> 42) & 0x7fff);
+			describe_control(desc);
+			break;
+		case 7:     // transfer (type 3)
+			describe_xfer3(desc);
+			break;
+
+		default:
+			return false;
+	}
+
+	return true;
+}
+
+void mb86235_frontend::describe_alu_input(opcode_desc &desc, int reg)
+{
+	switch (reg)
+	{
+		case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+			AA_USED(desc, reg & 7);
+			break;
+
+		case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+			AB_USED(desc, reg & 7);
+			break;
+
+		case 0x10:  // PR
+			break;
+
+		case 0x11:  // PR++
+			desc.userflags &= ~OP_USERFLAG_PR_MASK;
+			desc.userflags |= OP_USERFLAG_PR_INC;
+			break;
+		case 0x12:  // PR--
+			desc.userflags &= ~OP_USERFLAG_PR_MASK;
+			desc.userflags |= OP_USERFLAG_PR_DEC;
+			break;
+		case 0x13:  // PR#0
+			desc.userflags &= ~OP_USERFLAG_PR_MASK;
+			desc.userflags |= OP_USERFLAG_PR_ZERO;
+			break;
+
+
+		default:
+			break;
+	}
+}
+
+void mb86235_frontend::describe_mul_input(opcode_desc &desc, int reg)
+{
+	switch (reg)
+	{
+		case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+			MA_USED(desc, reg & 7);
+			break;
+
+		case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+			MB_USED(desc, reg & 7);
+			break;
+
+		case 0x10:  // PR
+			break;
+
+		case 0x11:  // PR++
+			if ((desc.userflags & OP_USERFLAG_PR_MASK) == 0)    // ALU PR update has higher priority
+			{
+				desc.userflags |= OP_USERFLAG_PR_INC;
+			}
+			break;
+		case 0x12:  // PR--
+			if ((desc.userflags & OP_USERFLAG_PR_MASK) == 0)    // ALU PR update has higher priority
+			{
+				desc.userflags |= OP_USERFLAG_PR_DEC;
+			}
+			break;
+		case 0x13:  // PR#0
+			if ((desc.userflags & OP_USERFLAG_PR_MASK) == 0)    // ALU PR update has higher priority
+			{
+				desc.userflags |= OP_USERFLAG_PR_ZERO;
+			}
+			break;
+
+		default:
+			break;
+	}
+}
+
+void mb86235_frontend::describe_alumul_output(opcode_desc &desc, int reg)
+{
+	switch (reg >> 3)
+	{
+		case 0:
+			MA_MODIFIED(desc, reg & 7);
+			break;
+
+		case 1:
+			MB_MODIFIED(desc, reg & 7);
+			break;
+
+		case 2:
+			AA_MODIFIED(desc, reg & 7);
+			break;
+
+		case 3:
+			AB_MODIFIED(desc, reg & 7);
+			break;
+
+		default:
+			break;
+	}
+}
+
+void mb86235_frontend::describe_reg_read(opcode_desc &desc, int reg)
+{
+	switch (reg)
+	{
+		case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+			// MA0-7
+			MA_USED(desc, reg & 7);
+			break;
+		case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+			// AA0-7
+			AA_USED(desc, reg & 7);
+			break;
+		case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+			// AR0-7
+			AR_USED(desc, reg & 7);
+			break;
+		case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
+			// MB0-7
+			MB_USED(desc, reg & 7);
+			break;
+		case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+			// AB0-7
+			AB_USED(desc, reg & 7);
+			break;
+
+		case 0x31:      // FI
+			desc.userflags |= OP_USERFLAG_FIFOIN;
+			desc.flags |= OPFLAG_IS_BRANCH_TARGET;      // fifo check makes this a branch target
+			break;
+
+		case 0x32:      // FO0
+			break;
+		case 0x33:      // FO1
+			break;
+
+		case 0x10:      // EB
+		case 0x11:      // EBU
+		case 0x12:      // EBL
+		case 0x13:      // EO
+		case 0x15:      // ST
+		case 0x16:      // MOD
+		case 0x17:      // LRPC
+		case 0x34:      // PDR
+		case 0x35:      // DDR
+		case 0x36:      // PRP
+		case 0x37:      // PWP
+			break;
+
+		case 0x30:      // PR
+			if ((desc.userflags & OP_USERFLAG_PR_MASK) == 0)        // ALU and MUL PR updates have higher priority
+			{
+				desc.userflags |= OP_USERFLAG_PR_INC;
+			}
+			break;
+	}
+}
+
+void mb86235_frontend::describe_reg_write(opcode_desc &desc, int reg)
+{
+	switch (reg)
+	{
+		case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+			// MA0-7
+			MA_MODIFIED(desc, reg & 7);
+			break;
+		case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+			// AA0-7
+			AA_MODIFIED(desc, reg & 7);
+			break;
+		case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+			// AR0-7
+			AR_MODIFIED(desc, reg & 7);
+			break;
+		case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
+			// MB0-7
+			MB_MODIFIED(desc, reg & 7);
+			break;
+		case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+			// AB0-7
+			AB_MODIFIED(desc, reg & 7);
+			break;
+
+		case 0x31:      // FI
+			break;
+
+		case 0x32:      // FO0
+			desc.userflags |= OP_USERFLAG_FIFOOUT0;
+			desc.flags |= OPFLAG_IS_BRANCH_TARGET;      // fifo check makes this a branch target
+			break;
+		case 0x33:      // FO1
+			desc.userflags |= OP_USERFLAG_FIFOOUT1;
+			desc.flags |= OPFLAG_IS_BRANCH_TARGET;      // fifo check makes this a branch target
+			break;
+
+		case 0x10:      // EB
+		case 0x11:      // EBU
+		case 0x12:      // EBL
+		case 0x13:      // EO
+		case 0x15:      // ST
+		case 0x16:      // MOD
+		case 0x17:      // LRPC
+		case 0x34:      // PDR
+		case 0x35:      // DDR
+		case 0x36:      // PRP
+		case 0x37:      // PWP
+			break;
+
+		case 0x30:      // PR
+			desc.userflags &= ~OP_USERFLAG_PW_MASK;
+			desc.userflags |= OP_USERFLAG_PW_INC;
+			break;
+	}
+}
+
+
+void mb86235_frontend::describe_alu(opcode_desc &desc, uint32_t aluop)
+{
+	int i1 = (aluop >> 10) & 0xf;
+	int i2 = (aluop >> 5) & 0x1f;
+	int io = aluop & 0x1f;
+	int op = (aluop >> 14) & 0x1f;
+
+	switch (op)
+	{
+		case 0x00:      // FADD
+			describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io);
+			AN_MODIFIED(desc);
+			AZ_MODIFIED(desc);
+			AV_MODIFIED(desc);
+			AU_MODIFIED(desc);
+			break;
+		case 0x01:      // FADDZ
+			describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io);
+			ZC_MODIFIED(desc);
+			AN_MODIFIED(desc);
+			AZ_MODIFIED(desc);
+			AV_MODIFIED(desc);
+			AU_MODIFIED(desc);
+			AD_MODIFIED(desc);
+			break;
+		case 0x02:      // FSUB
+			describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io);
+			AN_MODIFIED(desc);
+			AZ_MODIFIED(desc);
+			AV_MODIFIED(desc);
+			AU_MODIFIED(desc);
+			AD_MODIFIED(desc);
+			break;
+		case 0x03:      // FSUBZ
+			describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io);
+			ZC_MODIFIED(desc);
+			AN_MODIFIED(desc);
+			AZ_MODIFIED(desc);
+			AV_MODIFIED(desc);
+			AU_MODIFIED(desc);
+			AD_MODIFIED(desc);
+			break;
+		case 0x04:      // FCMP
+			describe_alu_input(desc, i1); describe_alu_input(desc, i2);
+			AN_MODIFIED(desc);
+			AZ_MODIFIED(desc);
+			AV_MODIFIED(desc);
+			AU_MODIFIED(desc);
+			AD_MODIFIED(desc);
+			break;
+		case 0x05:      // FABS
+			describe_alu_input(desc, i1); describe_alumul_output(desc, io);
+			AN_MODIFIED(desc);
+			AZ_MODIFIED(desc);
+			AD_MODIFIED(desc);
+			break;
+		case 0x06:      // FABC
+			describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io);
+			AN_MODIFIED(desc);
+			AZ_MODIFIED(desc);
+			AU_MODIFIED(desc);
+			AD_MODIFIED(desc);
+			break;
+		case 0x07:      // NOP
+			break;
+		case 0x08:      // FEA
+			describe_alu_input(desc, i1); describe_alumul_output(desc, io);
+			AN_MODIFIED(desc);
+			AZ_MODIFIED(desc);
+			AV_MODIFIED(desc);
+			AD_MODIFIED(desc);
+			break;
+		case 0x09:      // FES
+			describe_alu_input(desc, i1); describe_alumul_output(desc, io);
+			AN_MODIFIED(desc);
+			AZ_MODIFIED(desc);
+			AU_MODIFIED(desc);
+			AD_MODIFIED(desc);
+			break;
+		case 0x0a:      // FRCP
+			describe_alu_input(desc, i1); describe_alumul_output(desc, io);
+			ZD_MODIFIED(desc);
+			AN_MODIFIED(desc);
+			AZ_MODIFIED(desc);
+			AU_MODIFIED(desc);
+			AD_MODIFIED(desc);
+			break;
+		case 0x0b:      // FRSQ
+			describe_alu_input(desc, i1); describe_alumul_output(desc, io);
+			NR_MODIFIED(desc);
+			AN_MODIFIED(desc);
+			AZ_MODIFIED(desc);
+			AU_MODIFIED(desc);
+			AD_MODIFIED(desc);
+			break;
+		case 0x0c:      // FLOG
+			describe_alu_input(desc, i1); describe_alumul_output(desc, io);
+			IL_MODIFIED(desc);
+			AN_MODIFIED(desc);
+			AZ_MODIFIED(desc);
+			AD_MODIFIED(desc);
+			break;
+		case 0x0d:      // CIF
+			describe_alu_input(desc, i1); describe_alumul_output(desc, io);
+			AN_MODIFIED(desc);
+			AZ_MODIFIED(desc);
+			break;
+		case 0x0e:      // CFI
+			describe_alu_input(desc, i1); describe_alumul_output(desc, io);
+			AN_MODIFIED(desc);
+			AZ_MODIFIED(desc);
+			AV_MODIFIED(desc);
+			AD_MODIFIED(desc);
+			break;
+		case 0x0f:      // CFIB
+			describe_alu_input(desc, i1); describe_alumul_output(desc, io);
+			AN_MODIFIED(desc);
+			AZ_MODIFIED(desc);
+			AV_MODIFIED(desc);
+			AD_MODIFIED(desc);
+			AU_MODIFIED(desc);
+			break;
+		case 0x10:      // ADD
+			describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io);
+			AN_MODIFIED(desc);
+			AZ_MODIFIED(desc);
+			AV_MODIFIED(desc);
+			break;
+		case 0x11:      // ADDZ
+			describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io);
+			ZC_MODIFIED(desc);
+			AN_MODIFIED(desc);
+			AZ_MODIFIED(desc);
+			AV_MODIFIED(desc);
+			break;
+		case 0x12:      // SUB
+			describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io);
+			AN_MODIFIED(desc);
+			AZ_MODIFIED(desc);
+			AV_MODIFIED(desc);
+			break;
+		case 0x13:      // SUBZ
+			describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io);
+			ZC_MODIFIED(desc);
+			AN_MODIFIED(desc);
+			AZ_MODIFIED(desc);
+			AV_MODIFIED(desc);
+			break;
+		case 0x14:      // CMP
+			describe_alu_input(desc, i1); describe_alu_input(desc, i2);
+			AN_MODIFIED(desc);
+			AZ_MODIFIED(desc);
+			AV_MODIFIED(desc);
+			break;
+		case 0x15:      // ABS
+			describe_alu_input(desc, i1); describe_alumul_output(desc, io);
+			AN_MODIFIED(desc);
+			AZ_MODIFIED(desc);
+			AV_MODIFIED(desc);
+			break;
+		case 0x16:      // ATR
+			describe_alu_input(desc, i1); describe_alumul_output(desc, io);
+			break;
+		case 0x17:      // ATRZ
+			describe_alu_input(desc, i1); describe_alumul_output(desc, io);
+			ZC_MODIFIED(desc);
+			break;
+		case 0x18:      // AND
+			describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io);
+			AN_MODIFIED(desc);
+			AZ_MODIFIED(desc);
+			AV_MODIFIED(desc);
+			AU_MODIFIED(desc);
+			break;
+		case 0x19:      // OR
+			describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io);
+			AN_MODIFIED(desc);
+			AZ_MODIFIED(desc);
+			AV_MODIFIED(desc);
+			AU_MODIFIED(desc);
+			break;
+		case 0x1a:      // XOR
+			describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io);
+			AN_MODIFIED(desc);
+			AZ_MODIFIED(desc);
+			AV_MODIFIED(desc);
+			AU_MODIFIED(desc);
+			break;
+		case 0x1b:      // NOT
+			describe_alu_input(desc, i1); describe_alumul_output(desc, io);
+			AN_MODIFIED(desc);
+			AZ_MODIFIED(desc);
+			AV_MODIFIED(desc);
+			AU_MODIFIED(desc);
+			break;
+		case 0x1c:      // LSR
+			describe_alu_input(desc, i1); describe_alumul_output(desc, io);
+			AN_MODIFIED(desc);
+			AZ_MODIFIED(desc);
+			AV_MODIFIED(desc);
+			AU_MODIFIED(desc);
+			break;
+		case 0x1d:      // LSL
+			describe_alu_input(desc, i1); describe_alumul_output(desc, io);
+			AN_MODIFIED(desc);
+			AZ_MODIFIED(desc);
+			AV_MODIFIED(desc);
+			AU_MODIFIED(desc);
+			break;
+		case 0x1e:      // ASR
+			describe_alu_input(desc, i1); describe_alumul_output(desc, io);
+			AN_MODIFIED(desc);
+			AZ_MODIFIED(desc);
+			break;
+		case 0x1f:      // ASL
+			describe_alu_input(desc, i1); describe_alumul_output(desc, io);
+			AN_MODIFIED(desc);
+			AZ_MODIFIED(desc);
+			break;
+	}
+}
+
+void mb86235_frontend::describe_mul(opcode_desc &desc, uint32_t mulop)
+{
+	int i1 = (mulop >> 10) & 0xf;
+	int i2 = (mulop >> 5) & 0x1f;
+	int io = mulop & 0x1f;
+	int m = mulop & 0x4000;
+
+	describe_mul_input(desc, i1);
+	describe_mul_input(desc, i2);
+	describe_alumul_output(desc, io);
+
+	if (m)
+	{
+		// FMUL
+		MN_MODIFIED(desc);
+		MZ_MODIFIED(desc);
+		MV_MODIFIED(desc);
+		MU_MODIFIED(desc);
+		MD_MODIFIED(desc);
+	}
+	else
+	{
+		// MUL
+		MN_MODIFIED(desc);
+		MZ_MODIFIED(desc);
+		MV_MODIFIED(desc);
+	}
+}
+
+void mb86235_frontend::describe_ea(opcode_desc &desc, int md, int arx, int ary, int disp)
+{
+	switch (md)
+	{
+		case 0x0:       // @ARx
+			AR_USED(desc, arx);
+			break;
+		case 0x1:       // @ARx++
+			AR_USED(desc, arx); AR_MODIFIED(desc, arx);
+			break;
+		case 0x2:       // @ARx--
+			AR_USED(desc, arx); AR_MODIFIED(desc, arx);
+			break;
+		case 0x3:       // @ARx++disp
+			AR_USED(desc, arx); AR_MODIFIED(desc, arx);
+			break;
+		case 0x4:       // @ARx+ARy
+			AR_USED(desc, arx); AR_USED(desc, ary);
+			break;
+		case 0x5:       // @ARx+ARy++
+			AR_USED(desc, arx); AR_USED(desc, ary); AR_MODIFIED(desc, ary);
+			break;
+		case 0x6:       // @ARx+ARy--
+			AR_USED(desc, arx); AR_USED(desc, ary); AR_MODIFIED(desc, ary);
+			break;
+		case 0x7:       // @ARx+ARy++disp
+			AR_USED(desc, arx); AR_USED(desc, ary); AR_MODIFIED(desc, ary);
+			break;
+		case 0x8:       // @ARx+ARyU
+			AR_USED(desc, arx); AR_USED(desc, ary);
+			break;
+		case 0x9:       // @ARx+ARyL
+			AR_USED(desc, arx); AR_USED(desc, ary);
+			break;
+		case 0xa:       // @ARx+disp
+			AR_USED(desc, arx);
+			break;
+		case 0xb:       // @ARx+ARy+disp
+			AR_USED(desc, arx); AR_USED(desc, ary);
+			break;
+		case 0xc:       // @disp
+			break;
+		case 0xd:       // @ARx+[ARy++]
+			AR_USED(desc, arx); AR_USED(desc, ary); AR_MODIFIED(desc, ary);
+			break;
+		case 0xe:       // @ARx+[ARy--]
+			AR_USED(desc, arx); AR_USED(desc, ary); AR_MODIFIED(desc, ary);
+			break;
+		case 0xf:       // @ARx+[ARy++disp]
+			AR_USED(desc, arx); AR_USED(desc, ary); AR_MODIFIED(desc, ary);
+			break;
+	}
+}
+
+void mb86235_frontend::describe_xfer1(opcode_desc &desc)
+{
+	uint64_t opcode = desc.opptr.q[0];
+
+	int dr = (opcode >> 12) & 0x7f;
+	int sr = (opcode >> 19) & 0x7f;
+	int md = opcode & 0xf;
+	int ary = (opcode >> 4) & 7;
+	int disp5 = (opcode >> 7) & 0x1f;
+	int trm = (opcode >> 26) & 1;
+	int dir = (opcode >> 25) & 1;
+
+	if (trm == 0)
+	{
+		if ((sr & 0x40) == 0)
+		{
+			describe_reg_read(desc, sr & 0x3f);
+		}
+		else if (sr == 0x58)
+		{
+			// MOV1 #imm12, DR
+		}
+		else
+		{
+			describe_ea(desc, md, sr & 7, ary, disp5);
+			desc.flags |= OPFLAG_READS_MEMORY;
+		}
+
+		if ((dr & 0x40) == 0)
+		{
+			describe_reg_write(desc, dr & 0x3f);
+		}
+		else
+		{
+			describe_ea(desc, md, dr & 7, ary, disp5);
+			desc.flags |= OPFLAG_WRITES_MEMORY;
+		}
+	}
+	else
+	{
+		// external transfer
+		if (dir == 0)
+		{
+			describe_reg_read(desc, dr & 0x3f);
+			desc.flags |= OPFLAG_WRITES_MEMORY;
+		}
+		else
+		{
+			describe_reg_write(desc, dr & 0x3f);
+			desc.flags |= OPFLAG_READS_MEMORY;
+		}
+	}
+}
+
+void mb86235_frontend::describe_double_xfer1(opcode_desc &desc)
+{
+	uint64_t opcode = desc.opptr.q[0];
+
+	fatalerror("mb86235_frontend: describe_double_xfer1 at %08X (%08X%08X)", desc.pc, (uint32_t)(opcode >> 32), (uint32_t)(opcode));
+}
+
+void mb86235_frontend::describe_xfer2(opcode_desc &desc)
+{
+	uint64_t opcode = desc.opptr.q[0];
+
+	int op = (opcode >> 39) & 3;
+	int trm = (opcode >> 38) & 1;
+	int dir = (opcode >> 37) & 1;
+	int sr = (opcode >> 31) & 0x7f;
+	int dr = (opcode >> 24) & 0x7f;
+	int ary = (opcode >> 4) & 7;
+	int md = opcode & 0xf;
+	int disp14 = (opcode >> 7) & 0x3fff;
+
+	if (op == 0)    // MOV2
+	{
+		if (trm == 0)
+		{
+			if ((sr & 0x40) == 0)
+			{
+				describe_reg_read(desc, sr & 0x3f);
+			}
+			else if (sr == 0x58)
+			{
+				// MOV2 #imm24, DR
+			}
+			else
+			{
+				describe_ea(desc, md, sr & 7, ary, disp14);
+				desc.flags |= OPFLAG_READS_MEMORY;
+			}
+
+			if ((dr & 0x40) == 0)
+			{
+				describe_reg_write(desc, dr & 0x3f);
+			}
+			else
+			{
+				describe_ea(desc, md, dr & 7, ary, disp14);
+				desc.flags |= OPFLAG_WRITES_MEMORY;
+			}
+		}
+		else
+		{
+			// external transfer
+			if (dir == 0)
+			{
+				describe_reg_read(desc, dr & 0x3f);
+				desc.flags |= OPFLAG_WRITES_MEMORY;
+			}
+			else
+			{
+				describe_reg_write(desc, dr & 0x3f);
+				desc.flags |= OPFLAG_READS_MEMORY;
+			}
+		}
+	}
+	else if (op == 2)   // MOV4
+	{
+		fatalerror("mb86235_frontend: describe_xfer2 MOV4 at %08X (%08X%08X)", desc.pc, (uint32_t)(opcode >> 32), (uint32_t)(opcode));
+	}
+
+}
+
+void mb86235_frontend::describe_double_xfer2(opcode_desc &desc)
+{
+	uint64_t opcode = desc.opptr.q[0];
+	fatalerror("mb86235_frontend: describe_double_xfer2 at %08X (%08X%08X)", desc.pc, (uint32_t)(opcode >> 32), (uint32_t)(opcode));
+}
+
+void mb86235_frontend::describe_xfer3(opcode_desc &desc)
+{
+	uint64_t opcode = desc.opptr.q[0];
+
+	int dr = (opcode >> 19) & 0x7f;
+	int disp = (opcode >> 7) & 0xfff;
+	int ary = (opcode >> 4) & 7;
+	int md = opcode & 0xf;
+
+	switch (dr >> 5)
+	{
+		case 0:
+		case 1:     // reg
+			describe_reg_write(desc, dr & 0x3f);
+			break;
+
+		case 2:     // RAM-A
+		case 3:     // RAM-B
+			desc.flags |= OPFLAG_WRITES_MEMORY;
+			describe_ea(desc, md, dr & 7, ary, disp);
+			break;
+	}
+}
+
+void mb86235_frontend::describe_control(opcode_desc &desc)
+{
+	int ef1 = (desc.opptr.q[0] >> 16) & 0x3f;
+	int ef2 = desc.opptr.q[0] & 0xffff;
+	int cop = (desc.opptr.q[0] >> 22) & 0x1f;
+	int rel12 = (desc.opptr.q[0] & 0x800) ? (0xfffff000 | (desc.opptr.q[0] & 0xfff)) : (desc.opptr.q[0] & 0xfff);
+
+	switch (cop)
+	{
+		case 0x00:      // NOP
+			break;
+		case 0x01:      // REP
+			if (ef1 != 0)   // ARx
+				AR_USED(desc, (ef2 >> 12) & 7);
+
+			desc.userflags |= OP_USERFLAG_REPEAT;
+			break;
+		case 0x02:      // SETL
+			if (ef1 != 0)   // ARx
+				AR_USED(desc, (ef2 >> 12) & 7);
+			break;
+		case 0x03:      // CLRFI/CLRFO/CLRF
+			break;
+		case 0x04:      // PUSH
+			describe_reg_read(desc, (ef2 >> 6) & 0x3f);
+			break;
+		case 0x05:      // POP
+			describe_reg_write(desc, (ef2 >> 6) & 0x3f);
+			break;
+		case 0x08:      // SETM #imm16
+			break;
+		case 0x09:      // SETM #imm3, CBSA
+			break;
+		case 0x0a:      // SETM #imm3, CBSB
+			break;
+		case 0x0b:      // SETM #imm1, RF
+			break;
+		case 0x0c:      // SETM #imm1, RDY
+			break;
+		case 0x0d:      // SETM #imm1, WAIT
+			break;
+		case 0x13:      // DBLP rel12
+			desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+			desc.targetpc = desc.pc + rel12;
+			desc.delayslots = 1;
+			break;
+		case 0x14:      // DBBC ARx:y, rel12
+			desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+			desc.targetpc = desc.pc + rel12;
+			desc.delayslots = 1;
+			AR_USED(desc, ((desc.opptr.q[0] >> 13) & 7));
+			break;
+		case 0x15:      // DBBS ARx:y, rel12
+			desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+			desc.targetpc = desc.pc + rel12;
+			desc.delayslots = 1;
+			AR_USED(desc, ((desc.opptr.q[0] >> 13) & 7));
+			break;
+		case 0x1b:      // DRET
+			desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+			desc.targetpc = BRANCH_TARGET_DYNAMIC;
+			desc.delayslots = 1;
+			break;
+
+		case 0x10:      // DBcc
+		case 0x11:      // DBNcc
+		case 0x18:      // DCcc
+		case 0x19:      // DCNcc
+		{
+			switch ((desc.opptr.q[0] >> 12) & 0xf)
+			{
+				case 0x0: desc.targetpc = ef2 & 0xfff; break;
+				case 0x1: desc.targetpc = desc.pc + rel12; break;
+				case 0x2: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
+				case 0x3: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
+				case 0x4: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
+				case 0x5: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
+				case 0x6: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
+				case 0x7: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
+				case 0x8: desc.targetpc = BRANCH_TARGET_DYNAMIC; break;
+				case 0x9: desc.targetpc = BRANCH_TARGET_DYNAMIC; break;
+				case 0xa: desc.targetpc = BRANCH_TARGET_DYNAMIC; break;
+				case 0xb: desc.targetpc = BRANCH_TARGET_DYNAMIC; break;
+				case 0xc: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
+				case 0xd: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
+				case 0xe: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
+				case 0xf: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
+			}
+
+			desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+			desc.delayslots = 1;
+			break;
+		}
+
+		case 0x1a:      // DCALL
+		case 0x12:      // DJMP
+		{
+			switch ((desc.opptr.q[0] >> 12) & 0xf)
+			{
+				case 0x0: desc.targetpc = ef2 & 0xfff; break;
+				case 0x1: desc.targetpc = desc.pc + rel12; break;
+				case 0x2: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
+				case 0x3: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
+				case 0x4: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
+				case 0x5: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
+				case 0x6: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
+				case 0x7: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
+				case 0x8: desc.targetpc = BRANCH_TARGET_DYNAMIC; break;
+				case 0x9: desc.targetpc = BRANCH_TARGET_DYNAMIC; break;
+				case 0xa: desc.targetpc = BRANCH_TARGET_DYNAMIC; break;
+				case 0xb: desc.targetpc = BRANCH_TARGET_DYNAMIC; break;
+				case 0xc: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
+				case 0xd: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
+				case 0xe: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
+				case 0xf: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
+			}
+
+			desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+			desc.delayslots = 1;
+			break;
+		}
+	}
+}
diff --git a/src/devices/cpu/mb86235/mb86235fe.h b/src/devices/cpu/mb86235/mb86235fe.h
new file mode 100644
index 0000000..ef8bff0
--- /dev/null
+++ b/src/devices/cpu/mb86235/mb86235fe.h
@@ -0,0 +1,47 @@
+// license:BSD-3-Clause
+// copyright-holders:Ville Linde
+
+/******************************************************************************
+
+    Front-end for MB86235 recompiler
+
+******************************************************************************/
+
+#pragma once
+
+#include "mb86235.h"
+#include "cpu/drcfe.h"
+
+#ifndef __MB86235FE_H__
+#define __MB86235FE_H__
+
+class mb86235_frontend : public drc_frontend
+{
+public:
+	mb86235_frontend(mb86235_device *core, uint32_t window_start, uint32_t window_end, uint32_t max_sequence);
+
+protected:
+	// required overrides
+	virtual bool describe(opcode_desc &desc, const opcode_desc *prev) override;
+
+private:
+
+	mb86235_device *m_core;
+
+	void describe_alu(opcode_desc &desc, uint32_t aluop);
+	void describe_mul(opcode_desc &desc, uint32_t mulop);
+	void describe_xfer1(opcode_desc &desc);
+	void describe_double_xfer1(opcode_desc &desc);
+	void describe_xfer2(opcode_desc &desc);
+	void describe_double_xfer2(opcode_desc &desc);
+	void describe_xfer3(opcode_desc &desc);
+	void describe_control(opcode_desc &desc);
+	void describe_alu_input(opcode_desc &desc, int reg);
+	void describe_mul_input(opcode_desc &desc, int reg);
+	void describe_alumul_output(opcode_desc &desc, int reg);
+	void describe_reg_read(opcode_desc &desc, int reg);
+	void describe_reg_write(opcode_desc &desc, int reg);
+	void describe_ea(opcode_desc &desc, int md, int arx, int ary, int disp);
+};
+
+#endif /* __MB86235FE_H__ */
diff --git a/src/devices/cpu/powerpc/ppc.h b/src/devices/cpu/powerpc/ppc.h
index c51823f..b5db869 100644
--- a/src/devices/cpu/powerpc/ppc.h
+++ b/src/devices/cpu/powerpc/ppc.h
@@ -243,6 +243,7 @@ public:
 	void ppccom_tlb_flush();
 	void ppccom_execute_mfdcr();
 	void ppccom_execute_mtdcr();
+	void ppccom_get_dsisr();
 
 protected:
 	// device-level overrides
diff --git a/src/devices/cpu/powerpc/ppccom.cpp b/src/devices/cpu/powerpc/ppccom.cpp
index 2030489..bcdc17a 100644
--- a/src/devices/cpu/powerpc/ppccom.cpp
+++ b/src/devices/cpu/powerpc/ppccom.cpp
@@ -1498,6 +1498,27 @@ void ppc_device::ppccom_tlb_flush()
 ***************************************************************************/
 
 /*-------------------------------------------------
+    ppccom_get_dsisr - gets the DSISR value for a
+    failing TLB lookup's data access exception.
+-------------------------------------------------*/
+
+void ppc_device::ppccom_get_dsisr()
+{
+	int intent = 0;
+
+	if (m_core->param1 & 1)
+	{
+		intent = TRANSLATE_WRITE;
+	}
+	else
+	{
+		intent = TRANSLATE_READ;
+	}
+
+	m_core->param1 = ppccom_translate_address_internal(intent, m_core->param0);
+}
+
+/*-------------------------------------------------
     ppccom_execute_tlbie - execute a TLBIE
     instruction
 -------------------------------------------------*/
diff --git a/src/devices/cpu/powerpc/ppccom.h b/src/devices/cpu/powerpc/ppccom.h
index 3ec511e..ecd8e87 100644
--- a/src/devices/cpu/powerpc/ppccom.h
+++ b/src/devices/cpu/powerpc/ppccom.h
@@ -307,15 +307,15 @@ enum
 
 
 /* DSISR bits for DSI/alignment exceptions */
-#define DSISR_DIRECT        0x00000001      /* DSI: direct-store exception? */
-#define DSISR_NOT_FOUND     0x00000002      /* DSI: not found in HTEG or DBAT */
-#define DSISR_PROTECTED     0x00000010      /* DSI: exception due to protection */
-#define DSISR_CACHE_ERROR   0x00000020      /* DSI: operation on incorrect cache type */
-#define DSISR_STORE         0x00000040      /* DSI: store (1) or load (0) */
-#define DSISR_DABR          0x00000200      /* DSI: DABR match occurred */
-#define DSISR_NO_SEGMENT    0x00000400      /* DSI: no segment match found (64-bit only) */
-#define DSISR_INVALID_ECWX  0x00000800      /* DSI: ECIWX or ECOWX used with EAR[E] = 0 */
-#define DSISR_INSTRUCTION   0xfffff000      /* align: instruction decoding bits */
+#define DSISR_DIRECT        0x80000000      /* DSI: direct-store error interrupt */
+#define DSISR_NOT_FOUND     0x40000000      /* DSI: not found in HTEG or DBAT */
+#define DSISR_PROTECTED     0x08000000      /* DSI: exception due to protection */
+#define DSISR_CACHE_ERROR   0x04000000      /* DSI: operation on incorrect cache type */
+#define DSISR_STORE         0x02000000      /* DSI: store (1) or load (0) */
+#define DSISR_DABR          0x00400000      /* DSI: DABR match occurred */
+#define DSISR_NO_SEGMENT    0x00200000      /* DSI: no segment match found (64-bit only) */
+#define DSISR_INVALID_ECWX  0x00100000      /* DSI: ECIWX or ECOWX used with EAR[E] = 0 */
+#define DSISR_INSTRUCTION   0x000fffff      /* align: instruction decoding bits FIXME: mask/shift depends on addressing mode */
 
 
 /* PowerPC 4XX IRQ bits */
diff --git a/src/devices/cpu/powerpc/ppcdrc.cpp b/src/devices/cpu/powerpc/ppcdrc.cpp
index 6c98830..4ebf89a 100644
--- a/src/devices/cpu/powerpc/ppcdrc.cpp
+++ b/src/devices/cpu/powerpc/ppcdrc.cpp
@@ -642,6 +642,11 @@ static void cfunc_ppccom_execute_mtdcr(void *param)
 	ppc->ppccom_execute_mtdcr();
 }
 
+static void cfunc_ppccom_get_dsisr(void *param)
+{
+	ppc_device *ppc = (ppc_device *)param;
+	ppc->ppccom_get_dsisr();
+}
 
 /***************************************************************************
     STATIC CODEGEN
@@ -784,7 +789,11 @@ void ppc_device::static_generate_tlb_mismatch()
 	UML_LABEL(block, isi);                                                              // isi:
 	if (!(m_cap & PPCCAP_603_MMU))
 	{
-		UML_MOV(block, SPR32(SPROEA_DSISR), mem(&m_core->param0));                             // mov     [dsisr],[param0]
+		// DAR gets the address, DSISR gets the 'reason' flags
+		UML_MOV(block, SPR32(SPROEA_DAR), mem(&m_core->param0));             // mov     [dar],[param0]
+		m_core->param1 = 0; // always a read here
+		UML_CALLC(block, (c_function)cfunc_ppccom_get_dsisr, this);         // get DSISR to param1
+		UML_MOV(block, SPR32(SPROEA_DSISR), mem(&m_core->param1));          // move [dsisr], [param1]
 		UML_EXH(block, *m_exception[EXCEPTION_ISI], I0);                   // exh     isi,i0
 	}
 	else
@@ -1389,8 +1398,19 @@ void ppc_device::static_generate_memory_accessor(int mode, int size, int iswrite
 		/* general case: DSI exception */
 		else
 		{
-			UML_MOV(block, SPR32(SPROEA_DSISR), mem(&m_core->param0));                         // mov     [dsisr],[param0]
-			UML_EXH(block, *m_exception[EXCEPTION_DSI], I0);               // exh     dsi,i0
+			UML_MOV(block, SPR32(SPROEA_DAR), mem(&m_core->param0));            // mov [dar],[param0]
+			// signal read or write to cfunc to get proper reason back
+			if (iswrite)
+			{
+				m_core->param1 = 1;
+			}
+			else
+			{
+				m_core->param1 = 0;
+			}
+			UML_CALLC(block, (c_function)cfunc_ppccom_get_dsisr, this);         // get DSISR to param1
+			UML_MOV(block, SPR32(SPROEA_DSISR), mem(&m_core->param1));          // move [dsisr], [param1]
+			UML_EXH(block, *m_exception[EXCEPTION_DSI], I0);                    // exh dsi,i0
 		}
 	}
 
diff --git a/src/devices/cpu/sharc/sharc.cpp b/src/devices/cpu/sharc/sharc.cpp
index 2555d25..bfca220 100644
--- a/src/devices/cpu/sharc/sharc.cpp
+++ b/src/devices/cpu/sharc/sharc.cpp
@@ -52,29 +52,37 @@ enum
 	SHARC_B12,      SHARC_B13,      SHARC_B14,      SHARC_B15
 };
 
-
-#define ROPCODE(pc)     ((uint64_t)(m_internal_ram[((pc-0x20000) * 3) + 0]) << 32) | \
-						((uint64_t)(m_internal_ram[((pc-0x20000) * 3) + 1]) << 16) | \
-						((uint64_t)(m_internal_ram[((pc-0x20000) * 3) + 2]) << 0)
-
-
 const device_type ADSP21062 = &device_creator<adsp21062_device>;
 
-
-// This is just used to stop the debugger from complaining about executing from I/O space
 static ADDRESS_MAP_START( internal_pgm, AS_PROGRAM, 64, adsp21062_device )
-	AM_RANGE(0x20000, 0x7ffff) AM_RAM AM_SHARE("x")
+	AM_RANGE(0x20000, 0x24fff) AM_READWRITE(pm0_r, pm0_w)
+	AM_RANGE(0x28000, 0x2cfff) AM_READWRITE(pm1_r, pm1_w)
+	AM_RANGE(0x30000, 0x34fff) AM_READWRITE(pm1_r, pm1_w)
+	AM_RANGE(0x38000, 0x3cfff) AM_READWRITE(pm1_r, pm1_w)
 ADDRESS_MAP_END
 
+static ADDRESS_MAP_START( internal_data, AS_DATA, 32, adsp21062_device )
+	AM_RANGE(0x00000, 0x000ff) AM_READWRITE(iop_r, iop_w)
+	AM_RANGE(0x20000, 0x27fff) AM_RAM AM_SHARE("block0")
+	AM_RANGE(0x28000, 0x2ffff) AM_RAM AM_SHARE("block1")
+	AM_RANGE(0x30000, 0x37fff) AM_RAM AM_SHARE("block1")
+	AM_RANGE(0x38000, 0x3ffff) AM_RAM AM_SHARE("block1")
+	AM_RANGE(0x40000, 0x4ffff) AM_READWRITE(dmw0_r, dmw0_w)
+	AM_RANGE(0x50000, 0x5ffff) AM_READWRITE(dmw1_r, dmw1_w)
+	AM_RANGE(0x60000, 0x6ffff) AM_READWRITE(dmw1_r, dmw1_w)
+	AM_RANGE(0x70000, 0x7ffff) AM_READWRITE(dmw1_r, dmw1_w)
+ADDRESS_MAP_END
 
 adsp21062_device::adsp21062_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
 	: cpu_device(mconfig, ADSP21062, "ADSP21062", tag, owner, clock, "adsp21062", __FILE__)
 	, m_program_config("program", ENDIANNESS_LITTLE, 64, 24, -3, ADDRESS_MAP_NAME(internal_pgm))
-	, m_data_config("data", ENDIANNESS_LITTLE, 32, 32, -2)
+	, m_data_config("data", ENDIANNESS_LITTLE, 32, 32, -2, ADDRESS_MAP_NAME(internal_data))
 	, m_boot_mode(BOOT_MODE_HOST)
 	, m_cache(CACHE_SIZE + sizeof(sharc_internal_state))
 	, m_drcuml(nullptr)
 	, m_drcfe(nullptr)
+	, m_block0(*this, "block0")
+	, m_block1(*this, "block1")
 	, m_enable_drc(false)
 {
 }
@@ -88,7 +96,7 @@ offs_t adsp21062_device::disasm_disassemble(std::ostream &stream, offs_t pc, con
 
 void adsp21062_device::enable_recompiler()
 {
-	m_enable_drc = true;
+	m_enable_drc = allow_drc();
 }
 
 
@@ -144,11 +152,98 @@ void adsp21062_device::sharc_iop_delayed_w(uint32_t reg, uint32_t data, int cycl
 	m_core->delayed_iop_timer->adjust(cycles_to_attotime(cycles), 0);
 }
 
+// 0 012 0h 0l 1h
+// 1 453 2h 2l 1l
+// 2 678 3h 3l 4h
+// 3 ab9 5h 5l 4l
+// 4 cde 6h 6l 7h
+
+READ64_MEMBER( adsp21062_device::pm0_r)
+{
+	offs_t slot = offset >> 12;
+	offs_t base = (offset & 0xfff) + (slot >> 1) * (3<<12);
+	if(slot & 1)
+		return (uint64_t(m_block0[base + 0x2000]) << 16) | (m_block0[base + 0x1000] & 0xffff);
+	else
+		return (uint64_t(m_block0[base         ]) << 16) | (m_block0[base + 0x1000] >> 16);
+}
+
+WRITE64_MEMBER(adsp21062_device::pm0_w)
+{
+	offs_t slot = offset >> 12;
+	offs_t base = (offset & 0xfff) + (slot >> 1) * (3<<12);
+	if(slot & 1) {
+		if(ACCESSING_BITS_0_15)
+			m_block0[base + 0x1000] = (m_block0[base + 0x1000] & 0xffff0000) | (data & 0xffff);
+		m_block0[base + 0x2000] = (m_block0[base + 0x2000] & ~(mem_mask >> 16)) | ((data & mem_mask) >> 16);
+	} else {
+		m_block0[base + 0x0000] = (m_block0[base + 0x0000] & ~(mem_mask >> 16)) | ((data & mem_mask) >> 16);
+		if(ACCESSING_BITS_0_15)
+			m_block0[base + 0x1000] = (m_block0[base + 0x1000] & 0xffff) | ((data & 0xffff) << 16);
+	}
+}
+
+READ64_MEMBER( adsp21062_device::pm1_r)
+{
+	offs_t slot = offset >> 12;
+	offs_t base = (offset & 0xfff) + (slot >> 1) * (3<<12);
+	if(slot & 1)
+		return (uint64_t(m_block1[base + 0x2000]) << 16) | (m_block1[base + 0x1000] & 0xffff);
+	else
+		return (uint64_t(m_block1[base         ]) << 16) | (m_block1[base + 0x1000] >> 16);
+}
+
+WRITE64_MEMBER(adsp21062_device::pm1_w)
+{
+	offs_t slot = offset >> 12;
+	offs_t base = (offset & 0xfff) + (slot >> 1) * (3<<12);
+	if(slot & 1) {
+		if(ACCESSING_BITS_0_15)
+			m_block1[base + 0x1000] = (m_block1[base + 0x1000] & 0xffff0000) | (data & 0xffff);
+		m_block1[base + 0x2000] = (m_block1[base + 0x2000] & ~(mem_mask >> 16)) | ((data & mem_mask) >> 16);
+	} else {
+		m_block1[base + 0x0000] = (m_block1[base + 0x0000] & ~(mem_mask >> 16)) | ((data & mem_mask) >> 16);
+		if(ACCESSING_BITS_0_15)
+			m_block1[base + 0x1000] = (m_block1[base + 0x1000] & 0xffff) | ((data & 0xffff) << 16);
+	}
+}
+
+READ32_MEMBER( adsp21062_device::dmw0_r)
+{
+	if(offset & 1)
+		return m_block0[offset >> 1] >> 16;
+	else
+		return m_block0[offset >> 1] & 0xffff;
+}
+
+WRITE32_MEMBER(adsp21062_device::dmw0_w)
+{
+	if(offset & 1)
+		m_block0[offset >> 1] = (m_block0[offset >> 1] & 0xffff) | (data << 16);
+	else
+		m_block0[offset >> 1] = (m_block0[offset >> 1] & 0xffff0000) | (data & 0xffff);
+}
+
+READ32_MEMBER( adsp21062_device::dmw1_r)
+{
+	if(offset & 1)
+		return m_block1[offset >> 1] >> 16;
+	else
+		return m_block1[offset >> 1] & 0xffff;
+}
+
+WRITE32_MEMBER(adsp21062_device::dmw1_w)
+{
+	if(offset & 1)
+		m_block1[offset >> 1] = (m_block1[offset >> 1] & 0xffff) | (data << 16);
+	else
+		m_block1[offset >> 1] = (m_block1[offset >> 1] & 0xffff0000) | (data & 0xffff);
+}
 
 /* IOP registers */
-uint32_t adsp21062_device::sharc_iop_r(uint32_t address)
+READ32_MEMBER( adsp21062_device::iop_r)
 {
-	switch (address)
+	switch (offset)
 	{
 		case 0x00: return 0;    // System configuration
 
@@ -156,13 +251,13 @@ uint32_t adsp21062_device::sharc_iop_r(uint32_t address)
 		{
 			return m_core->dma_status;
 		}
-		default:        fatalerror("sharc_iop_r: Unimplemented IOP reg %02X at %08X\n", address, m_core->pc);
+		default:        fatalerror("sharc_iop_r: Unimplemented IOP reg %02X at %08X\n", offset, m_core->pc);
 	}
 }
 
-void adsp21062_device::sharc_iop_w(uint32_t address, uint32_t data)
+WRITE32_MEMBER(adsp21062_device::iop_w)
 {
-	switch (address)
+	switch (offset)
 	{
 		case 0x00: break;       // System configuration
 		case 0x02: break;       // External Memory Wait State Configuration
@@ -240,7 +335,7 @@ void adsp21062_device::sharc_iop_w(uint32_t address, uint32_t data)
 		case 0x4e: m_core->dma[7].ext_modifier = data; return;
 		case 0x4f: m_core->dma[7].ext_count = data; return;
 
-		default:        fatalerror("sharc_iop_w: Unimplemented IOP reg %02X, %08X at %08X\n", address, data, m_core->pc);
+		default:        fatalerror("sharc_iop_w: Unimplemented IOP reg %02X, %08X at %08X\n", offset, data, m_core->pc);
 	}
 }
 
@@ -297,7 +392,7 @@ void adsp21062_device::external_iop_write(uint32_t address, uint32_t data)
 	else
 	{
 		osd_printf_debug("SHARC IOP write %08X, %08X\n", address, data);
-		sharc_iop_w(address, data);
+		m_data->write_dword(address << 2, data);
 	}
 }
 
@@ -341,14 +436,10 @@ void adsp21062_device::device_start()
 	memset(m_core, 0, sizeof(sharc_internal_state));
 
 	m_program = &space(AS_PROGRAM);
-	m_direct = &m_program->direct();
 	m_data = &space(AS_DATA);
 
 	build_opcode_table();
 
-	m_internal_ram_block0 = &m_internal_ram[0];
-	m_internal_ram_block1 = &m_internal_ram[0x20000/2];
-
 	// init UML generator
 	uint32_t umlflags = 0;
 	m_drcuml = std::make_unique<drcuml_state>(*this, m_cache, umlflags, 1, 24, 0);
@@ -615,8 +706,6 @@ void adsp21062_device::device_start()
 
 	save_item(NAME(m_core->px));
 
-	save_pointer(NAME(m_internal_ram), 2 * 0x10000);
-
 	save_item(NAME(m_core->opcode));
 
 	save_item(NAME(m_core->nfaddr));
@@ -767,7 +856,8 @@ void adsp21062_device::device_start()
 
 void adsp21062_device::device_reset()
 {
-	memset(m_internal_ram, 0, 2 * 0x10000 * sizeof(uint16_t));
+	memset(m_block0, 0, 0x8000 * sizeof(uint32_t));
+	memset(m_block1, 0, 0x8000 * sizeof(uint32_t));
 
 	switch(m_boot_mode)
 	{
@@ -898,6 +988,12 @@ void adsp21062_device::check_interrupts()
 
 void adsp21062_device::execute_run()
 {
+	static bool first = true;
+	if(first) {
+		first = false;
+		machine().debug_break();
+	}
+
 	if (m_enable_drc)
 	{
 		if (m_core->irq_pending != 0)
@@ -931,9 +1027,15 @@ void adsp21062_device::execute_run()
 			m_core->astat_old_old = m_core->astat_old;
 			m_core->astat_old = m_core->astat;
 
+			static bool first = true;
+			if(first) {
+				first = false;
+				machine().debug_break();
+			}
+
 			debugger_instruction_hook(this, m_core->pc);
 
-			m_core->opcode = ROPCODE(m_core->pc);
+			m_core->opcode = m_program->read_qword(m_core->pc << 3);
 
 			// handle looping
 			if (m_core->pc == m_core->laddr.addr)
@@ -1011,92 +1113,3 @@ void adsp21062_device::execute_run()
 		};
 	}
 }
-
-bool adsp21062_device::memory_read(address_spacenum spacenum, offs_t offset, int size, uint64_t &value)
-{
-	if (spacenum == AS_PROGRAM)
-	{
-		int address = offset >> 3;
-
-		if (address >= 0x20000 && address < 0x30000)
-		{
-			switch (size)
-			{
-				case 1:
-				{
-					int frac = offset & 7;
-					value = (pm_read48(offset >> 3) >> ((frac^7) * 8)) & 0xff;
-					break;
-				}
-				case 8:
-				{
-					value = pm_read48(offset >> 3);
-					break;
-				}
-			}
-		}
-		else
-		{
-			value = 0;
-		}
-	}
-	else if (spacenum == AS_DATA)
-	{
-		int address = offset >> 2;
-
-		if (address >= 0x20000)
-		{
-			switch (size)
-			{
-				case 1:
-				{
-					int frac = offset & 3;
-					value = (dm_read32(offset >> 2) >> ((frac^3) * 8)) & 0xff;
-					break;
-				}
-				case 2:
-				{
-					int frac = (offset >> 1) & 1;
-					value = (dm_read32(offset >> 2) >> ((frac^1) * 16)) & 0xffff;
-					break;
-				}
-				case 4:
-				{
-					value = dm_read32(offset >> 2);
-					break;
-				}
-			}
-		}
-		else
-		{
-			value = 0;
-		}
-	}
-	return true;
-}
-
-bool adsp21062_device::memory_readop(offs_t offset, int size, uint64_t &value)
-{
-	uint64_t mask = (size < 8) ? (((uint64_t)1 << (8 * size)) - 1) : ~(uint64_t)0;
-	int shift = 8 * (offset & 7);
-	offset >>= 3;
-
-	if (offset >= 0x20000 && offset < 0x28000)
-	{
-		uint64_t op = ((uint64_t)(m_internal_ram_block0[((offset-0x20000) * 3) + 0]) << 32) |
-					((uint64_t)(m_internal_ram_block0[((offset-0x20000) * 3) + 1]) << 16) |
-					((uint64_t)(m_internal_ram_block0[((offset-0x20000) * 3) + 2]) << 0);
-		value = (op >> shift) & mask;
-		return true;
-	}
-	else if (offset >= 0x28000 && offset < 0x30000)
-	{
-		uint64_t op = ((uint64_t)(m_internal_ram_block1[((offset-0x28000) * 3) + 0]) << 32) |
-					((uint64_t)(m_internal_ram_block1[((offset-0x28000) * 3) + 1]) << 16) |
-					((uint64_t)(m_internal_ram_block1[((offset-0x28000) * 3) + 2]) << 0);
-		value = (op >> shift) & mask;
-		return true;
-	}
-
-	return false;
-}
diff --git a/src/devices/cpu/sharc/sharc.h b/src/devices/cpu/sharc/sharc.h
index 7d36321..51625c7 100644
--- a/src/devices/cpu/sharc/sharc.h
+++ b/src/devices/cpu/sharc/sharc.h
@@ -171,6 +171,17 @@ public:
 
 	void enable_recompiler();
 
+	DECLARE_READ64_MEMBER( pm0_r);
+	DECLARE_WRITE64_MEMBER(pm0_w);
+	DECLARE_READ64_MEMBER( pm1_r);
+	DECLARE_WRITE64_MEMBER(pm1_w);
+	DECLARE_READ32_MEMBER( dmw0_r);
+	DECLARE_WRITE32_MEMBER(dmw0_w);
+	DECLARE_READ32_MEMBER( dmw1_r);
+	DECLARE_WRITE32_MEMBER(dmw1_w);
+	DECLARE_READ32_MEMBER( iop_r);
+	DECLARE_WRITE32_MEMBER(iop_w);
+
 	enum ASTAT_FLAGS
 	{
 		// ASTAT flags
@@ -257,16 +268,12 @@ protected:
 
 	// device_memory_interface overrides
 	virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const override { return (spacenum == AS_PROGRAM) ? &m_program_config : ( (spacenum == AS_DATA) ? &m_data_config : nullptr ); }
-	virtual bool memory_read(address_spacenum spacenum, offs_t offset, int size, uint64_t &value) override;
-	virtual bool memory_readop(offs_t offset, int size, uint64_t &value) override;
 
 	// device_disasm_interface overrides
 	virtual uint32_t disasm_min_opcode_bytes() const override { return 6; }
 	virtual uint32_t disasm_max_opcode_bytes() const override { return 6; }
 	virtual offs_t disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) override;
 
-	direct_read_data *m_direct;
-
 private:
 	address_space_config m_program_config;
 	address_space_config m_data_config;
@@ -448,21 +455,18 @@ private:
 	uml::code_handle *m_swap_r0_7;
 	uml::code_handle *m_swap_r8_15;
 
-	uint16_t *m_internal_ram_block0, *m_internal_ram_block1;
-
 	address_space *m_program;
 	address_space *m_data;
-	opcode_func m_sharc_op[512];
 
-	uint16_t m_internal_ram[2 * 0x10000]; // 2x 128KB
+	required_shared_ptr<uint32_t> m_block0, m_block1;
+
+	opcode_func m_sharc_op[512];
 
 	bool m_enable_drc;
 
 	inline void CHANGE_PC(uint32_t newpc);
 	inline void CHANGE_PC_DELAYED(uint32_t newpc);
 	void sharc_iop_delayed_w(uint32_t reg, uint32_t data, int cycles);
-	uint32_t sharc_iop_r(uint32_t address);
-	void sharc_iop_w(uint32_t address, uint32_t data);
 	uint32_t pm_read32(uint32_t address);
 	void pm_write32(uint32_t address, uint32_t data);
 	uint64_t pm_read48(uint32_t address);
diff --git a/src/devices/cpu/sharc/sharcdrc.cpp b/src/devices/cpu/sharc/sharcdrc.cpp
index 5eaacd5..b8ab1a1 100644
--- a/src/devices/cpu/sharc/sharcdrc.cpp
+++ b/src/devices/cpu/sharc/sharcdrc.cpp
@@ -18,7 +18,6 @@
 using namespace uml;
 
 #define USE_SWAPDQ  0
-#define WRITE_SNOOP 0
 
 
 // map variables
@@ -114,24 +113,13 @@ inline void adsp21062_device::alloc_handle(drcuml_state *drcuml, code_handle **h
 
 
 
+
 static void cfunc_unimplemented(void *param)
 {
 	adsp21062_device *sharc = (adsp21062_device *)param;
 	sharc->sharc_cfunc_unimplemented();
 }
 
-static void cfunc_read_iop(void *param)
-{
-	adsp21062_device *sharc = (adsp21062_device *)param;
-	sharc->sharc_cfunc_read_iop();
-}
-
-static void cfunc_write_iop(void *param)
-{
-	adsp21062_device *sharc = (adsp21062_device *)param;
-	sharc->sharc_cfunc_write_iop();
-}
-
 static void cfunc_pcstack_overflow(void *param)
 {
 	adsp21062_device *sharc = (adsp21062_device *)param;
@@ -180,21 +168,6 @@ static void cfunc_unimplemented_shiftimm(void *param)
 	sharc->sharc_cfunc_unimplemented_shiftimm();
 }
 
-
-#if WRITE_SNOOP
-void adsp21062_device::sharc_cfunc_write_snoop()
-{
-	printf("Write %08X to %08X at %08X\n", m_core->arg0, m_core->arg1, m_core->arg2);
-}
-
-static void cfunc_write_snoop(void *param)
-{
-	adsp21062_device *sharc = (adsp21062_device *)param;
-	sharc->sharc_cfunc_write_snoop();
-}
-#endif
-
-
 void adsp21062_device::sharc_cfunc_unimplemented()
 {
 	uint64_t op = m_core->arg64;
@@ -213,16 +186,6 @@ void adsp21062_device::sharc_cfunc_unimplemented_shiftimm()
 	fatalerror("PC=%08X: Unimplemented shiftimm %04X%08X\n", m_core->pc, (uint32_t)(op >> 32), (uint32_t)(op));
 }
 
-void adsp21062_device::sharc_cfunc_read_iop()
-{
-	m_core->arg1 = sharc_iop_r(m_core->arg0);
-}
-
-void adsp21062_device::sharc_cfunc_write_iop()
-{
-	sharc_iop_w(m_core->arg0, m_core->arg1);
-}
-
 void adsp21062_device::sharc_cfunc_pcstack_overflow()
 {
 	fatalerror("SHARC: PCStack overflow");
@@ -334,16 +297,6 @@ void adsp21062_device::static_generate_memory_accessor(MEM_ACCESSOR_TYPE type, c
 {
 	// I0 = read/write data
 	// I1 = address
-	// I2 is trashed
-
-	void* block0 = &m_internal_ram_block0[0];
-	void* block0_1 = &m_internal_ram_block0[1];
-	void* block0_2 = &m_internal_ram_block0[2];
-	void* block1 = &m_internal_ram_block1[0];
-	void* block1_1 = &m_internal_ram_block1[1];
-	void* block1_2 = &m_internal_ram_block1[2];
-
-	code_label label = 1;
 
 	drcuml_block *block = m_drcuml->begin_block(1024);
 
@@ -354,298 +307,35 @@ void adsp21062_device::static_generate_memory_accessor(MEM_ACCESSOR_TYPE type, c
 	switch (type)
 	{
 		case MEM_ACCESSOR_PM_READ48:
-			UML_CMP(block, I1, IRAM_BLOCK0_START);                      // cmp     i1,IRAM_BLOCK0_START
-			UML_JMPc(block, COND_B, label);                             // jb      label1
-			UML_CMP(block, I1, IRAM_BLOCK0_END);                        // cmp     i1,IRAM_BLOCK0_END
-			UML_JMPc(block, COND_A, label);                             // ja      label1
-
-			// 0x20000 ... 0x27fff
-			UML_AND(block, I1, I1, 0x7fff);                             // and     i1,i1,0x7fff
-			UML_MULS(block, I1, I1, I1, 3);                             // muls    i1,3
-			UML_DLOAD(block, I0, block0, I1, SIZE_WORD, SCALE_x2);      // dload   i0,[block0],i1,word,scale_x2
-			UML_DSHL(block, I0, I0, 32);                                // dshl    i0,i0,32
-			UML_DLOAD(block, I2, block0_1, I1, SIZE_WORD, SCALE_x2);    // dload   i2,[block0_1],i1,word,scale_x2
-			UML_DSHL(block, I2, I2, 16);                                // dshl    i2,i2,16
-			UML_DOR(block, I0, I0, I2);                                 // dor     i0,i0,i2
-			UML_DLOAD(block, I2, block0_2, I1, SIZE_WORD, SCALE_x2);    // dload   i2,[block0_2],i1,word,scale_x2
-			UML_DOR(block, I0, I0, I2);                                 // dor     i0,i0,i2
-			UML_RET(block);                                             // ret
-
-			UML_LABEL(block, label++);                                  // label1:
-			UML_CMP(block, I1, IRAM_BLOCK1_START);                      // cmp     i1,IRAM_BLOCK1_START
-			UML_JMPc(block, COND_B, label);                             // jb      label2
-			UML_CMP(block, I1, IRAM_BLOCK1_END);                        // cmp     i1,IRAM_BLOCK1_END
-			UML_JMPc(block, COND_A, label);                             // ja      label2
-
-			// 0x28000  ... 0x3ffff
-			UML_AND(block, I1, I1, 0x7fff);                             // and     i1,i1,0x7fff (block 1 is mirrored in 0x28000...2ffff, 0x30000...0x37fff and 0x38000...3ffff)
-			UML_MULS(block, I1, I1, I1, 3);                             // muls    i1,3
-			UML_DLOAD(block, I0, block1, I1, SIZE_WORD, SCALE_x2);      // dload   i0,[block1],i1,word,scale_x2
-			UML_DSHL(block, I0, I0, 32);                                // dshl    i0,i0,32
-			UML_DLOAD(block, I2, block1_1, I1, SIZE_WORD, SCALE_x2);    // dload   i2,[block1_1],i1,word,scale_x2
-			UML_DSHL(block, I2, I2, 16);                                // dshl    i2,i2,16
-			UML_DOR(block, I0, I0, I2);                                 // dor     i0,i0,i2
-			UML_DLOAD(block, I2, block1_2, I1, SIZE_WORD, SCALE_x2);    // dload   i2,[block1_2],i1,word,scale_x2
-			UML_DOR(block, I0, I0, I2);                                 // dor     i0,i0,i2
-			UML_RET(block);                                             // ret
-
-			UML_LABEL(block, label++);                                  // label2:
+			UML_SHL(block, I1, I1, 3);
+			UML_DREAD(block, I0, I1, SIZE_QWORD, SPACE_PROGRAM);
 			break;
 
 		case MEM_ACCESSOR_PM_WRITE48:
-			UML_CMP(block, I1, IRAM_BLOCK0_START);                      // cmp     i1,IRAM_BLOCK0_START
-			UML_JMPc(block, COND_B, label);                             // jb      label1
-			UML_CMP(block, I1, IRAM_BLOCK0_END);                        // cmp     i1,IRAM_BLOCK0_END
-			UML_JMPc(block, COND_A, label);                             // ja      label1
-
-			// 0x20000 ... 0x27fff
-			UML_AND(block, I1, I1, 0x7fff);                             // and     i1,i1,0x7fff
-			UML_MULS(block, I1, I1, I1, 3);                             // muls    i1,3
-			UML_DSTORE(block, block0_2, I1, I0, SIZE_WORD, SCALE_x2);   // dstore  [block0_2],i1,i0,word,scale_x2
-			UML_DSHR(block, I0, I0, 16);                                // dshr    i0,i0,16
-			UML_DSTORE(block, block0_1, I1, I0, SIZE_WORD, SCALE_x2);   // dstore  [block0_1],i1,i0,word,scale_x2
-			UML_DSHR(block, I0, I0, 16);                                // dshr    i0,i0,16
-			UML_DSTORE(block, block0, I1, I0, SIZE_WORD, SCALE_x2);     // dstore  [block0],i1,i0,word,scale_x2
+			UML_SHL(block, I1, I1, 3);
+			UML_DWRITE(block, I1, I0, SIZE_QWORD, SPACE_PROGRAM);
 			UML_MOV(block, mem(&m_core->force_recompile), 1);
-			UML_RET(block);                                             // ret
-
-			UML_LABEL(block, label++);                                  // label1:
-			UML_CMP(block, I1, IRAM_BLOCK1_START);                      // cmp     i1,IRAM_BLOCK1_START
-			UML_JMPc(block, COND_B, label);                             // jb      label2
-			UML_CMP(block, I1, IRAM_BLOCK1_END);                        // cmp     i1,IRAM_BLOCK1_END
-			UML_JMPc(block, COND_A, label);                             // ja      label2
-
-			// 0x28000  ... 0x3ffff
-			UML_AND(block, I1, I1, 0x7fff);                             // and     i1,i1,0x7fff (block 1 is mirrored in 0x28000...2ffff, 0x30000...0x37fff and 0x38000...3ffff)
-			UML_MULS(block, I1, I1, I1, 3);                             // muls    i1,3
-			UML_DSTORE(block, block1_2, I1, I0, SIZE_WORD, SCALE_x2);   // dstore  [block1_2],i1,i0,word,scale_x2
-			UML_DSHR(block, I0, I0, 16);                                // dshr    i0,i0,16
-			UML_DSTORE(block, block1_1, I1, I0, SIZE_WORD, SCALE_x2);   // dstore  [block1_1],i1,i0,word,scale_x2
-			UML_DSHR(block, I0, I0, 16);                                // dshr    i0,i0,16
-			UML_DSTORE(block, block1, I1, I0, SIZE_WORD, SCALE_x2);     // dstore  [block1],i1,i0,word,scale_x2
-			UML_RET(block);                                             // ret
-
-			UML_LABEL(block, label++);                                  // label2:
 			break;
 
 		case MEM_ACCESSOR_PM_READ32:
-			UML_CMP(block, I1, IRAM_BLOCK0_START);                      // cmp     i1,IRAM_BLOCK0_START
-			UML_JMPc(block, COND_B, label);                             // jb      label1
-			UML_CMP(block, I1, IRAM_BLOCK0_END);                        // cmp     i1,IRAM_BLOCK0_END
-			UML_JMPc(block, COND_A, label);                             // ja      label1
-
-			// 0x20000 ... 0x27fff
-			UML_AND(block, I1, I1, 0x7fff);                             // and     i1,i1,0x7fff
-			UML_MULS(block, I1, I1, I1, 3);                             // muls    i1,3
-			UML_LOAD(block, I0, block0, I1, SIZE_WORD, SCALE_x2);       // load    i0,[block0],i1,word,scale_x2
-			UML_SHL(block, I0, I0, 16);                                 // shl     i0,i0,16
-			UML_LOAD(block, I2, block0_1, I1, SIZE_WORD, SCALE_x2);     // load    i2,[block0_1],i1,word,scale_x2
-			UML_OR(block, I0, I0, I2);                                  // or      i0,i0,i2
-			UML_RET(block);                                             // ret
-
-			UML_LABEL(block, label++);                                  // label1:
-			UML_CMP(block, I1, IRAM_BLOCK1_START);                      // cmp     i1,IRAM_BLOCK1_START
-			UML_JMPc(block, COND_B, label);                             // jb      label2
-			UML_CMP(block, I1, IRAM_BLOCK1_END);                        // cmp     i1,IRAM_BLOCK1_END
-			UML_JMPc(block, COND_A, label);                             // ja      label2
-
-			// 0x28000  ... 0x3ffff
-			UML_AND(block, I1, I1, 0x7fff);                             // and     i1,i1,0x7fff (block 1 is mirrored in 0x28000...2ffff, 0x30000...0x37fff and 0x38000...3ffff)
-			UML_MULS(block, I1, I1, I1, 3);                             // muls    i1,3
-			UML_LOAD(block, I0, block1, I1, SIZE_WORD, SCALE_x2);       // load    i0,[block1],i1,word,scale_x2
-			UML_SHL(block, I0, I0, 16);                                 // shl     i0,i0,16
-			UML_LOAD(block, I2, block1_1, I1, SIZE_WORD, SCALE_x2);     // load    i2,[block1_1],i1,word,scale_x2
-			UML_OR(block, I0, I0, I2);                                  // or      i0,i0,i2
-			UML_RET(block);                                             // ret
-
-			UML_LABEL(block, label++);                                  // label2:
+			UML_SHL(block, I1, I1, 3);
+			UML_READ(block, I0, I1, SIZE_DWORD, SPACE_PROGRAM);
 			break;
 
 		case MEM_ACCESSOR_PM_WRITE32:
-			UML_CMP(block, I1, IRAM_BLOCK0_START);                      // cmp     i1,IRAM_BLOCK0_START
-			UML_JMPc(block, COND_B, label);                             // jb      label1
-			UML_CMP(block, I1, IRAM_BLOCK0_END);                        // cmp     i1,IRAM_BLOCK0_END
-			UML_JMPc(block, COND_A, label);                             // ja      label1
-
-			// 0x20000 ... 0x27fff
-			UML_AND(block, I1, I1, 0x7fff);                             // and     i1,i1,0x7fff
-			UML_MULS(block, I1, I1, I1, 3);                             // muls    i1,3
-			UML_STORE(block, block0_1, I1, I0, SIZE_WORD, SCALE_x2);    // store   [block0_1],i1,i0,word,scale_x2
-			UML_SHR(block, I0, I0, 16);                                 // shr     i0,i0,16
-			UML_STORE(block, block0, I1, I0, SIZE_WORD, SCALE_x2);      // store   [block0],i1,i0,word,scale_x2
-			UML_RET(block);                                             // ret
-
-			UML_LABEL(block, label++);                                  // label1:
-			UML_CMP(block, I1, IRAM_BLOCK1_START);                      // cmp     i1,IRAM_BLOCK1_START
-			UML_JMPc(block, COND_B, label);                             // jb      label2
-			UML_CMP(block, I1, IRAM_BLOCK1_END);                        // cmp     i1,IRAM_BLOCK1_END
-			UML_JMPc(block, COND_A, label);                             // ja      label2
-
-			// 0x28000  ... 0x3ffff
-			UML_AND(block, I1, I1, 0x7fff);                             // and     i1,i1,0x7fff (block 1 is mirrored in 0x28000...2ffff, 0x30000...0x37fff and 0x38000...3ffff)
-			UML_MULS(block, I1, I1, I1, 3);                             // muls    i1,3
-			UML_STORE(block, block1_1, I1, I0, SIZE_WORD, SCALE_x2);    // store   [block1_1],i1,i0,word,scale_x2
-			UML_SHR(block, I0, I0, 16);                                 // shr     i0,i0,16
-			UML_STORE(block, block1, I1, I0, SIZE_WORD, SCALE_x2);      // store   [block1],i1,i0,word,scale_x2
-			UML_RET(block);                                             // ret
-
-			UML_LABEL(block, label++);                                  // label2:
+			UML_SHL(block, I1, I1, 3);
+			UML_WRITE(block, I1, I0, SIZE_DWORD, SPACE_PROGRAM);
+			UML_MOV(block, mem(&m_core->force_recompile), 1);
 			break;
 
 		case MEM_ACCESSOR_DM_READ32:
-			UML_CMP(block, I1, IRAM_END);                               // cmp     i1,IRAM_END
-			UML_JMPc(block, COND_BE, label);                            // jbe     label1
-			// 0x80000 ...
-			UML_SHL(block, I1, I1, 2);                                  // shl     i1,i1,2
-			UML_READ(block, I0, I1, SIZE_DWORD, SPACE_DATA);            // read    i0,i1,dword,SPACE_DATA
-			UML_RET(block);
-
-			UML_LABEL(block, label++);                                  // label1:
-			UML_CMP(block, I1, IRAM_BLOCK0_START);                      // cmp     i1,IRAM_BLOCK0_START
-			UML_JMPc(block, COND_B, label);                             // jb      label2
-			UML_CMP(block, I1, IRAM_BLOCK0_END);                        // cmp     i1,IRAM_BLOCK0_END
-			UML_JMPc(block, COND_A, label);                             // ja      label2
-			// 0x20000 ... 0x27fff
-			UML_AND(block, I1, I1, 0x7fff);                             // and     i1,i1,0x7fff
-			UML_LOAD(block, I0, block0, I1, SIZE_WORD, SCALE_x4);       // load    i0,[block0],i1,word,scale_x4
-			UML_SHL(block, I0, I0, 16);                                 // shl     i0,i0,16
-			UML_LOAD(block, I2, block0_1, I1, SIZE_WORD, SCALE_x4);     // load    i2,[block0_1],i1,word,scale_x4
-			UML_OR(block, I0, I0, I2);                                  // or      i0,i0,i2
-			UML_RET(block);
-
-			UML_LABEL(block, label++);                                  // label2:
-			UML_CMP(block, I1, IRAM_BLOCK1_START);                      // cmp     i1,IRAM_BLOCK1_START
-			UML_JMPc(block, COND_B, label);                             // jb      label3
-			UML_CMP(block, I1, IRAM_BLOCK1_END);                        // cmp     i1,IRAM_BLOCK1_END
-			UML_JMPc(block, COND_A, label);                             // ja      label3
-			// 0x28000 ... 0x3ffff
-			UML_AND(block, I1, I1, 0x7fff);                             // and     i1,i1,0x7fff
-			UML_LOAD(block, I0, block1, I1, SIZE_WORD, SCALE_x4);       // load    i0,[block1],i1,word,scale_x4
-			UML_SHL(block, I0, I0, 16);                                 // shl     i0,i0,16
-			UML_LOAD(block, I2, block1_1, I1, SIZE_WORD, SCALE_x4);     // load    i2,[block1_1],i1,word,scale_x4
-			UML_OR(block, I0, I0, I2);                                  // or      i0,i0,i2
-			UML_RET(block);
-
-			UML_LABEL(block, label++);                                  // Label3:
-			UML_CMP(block, I1, IOP_REGISTER_END);                       // cmp     i1,IOP_REGISTER_END
-			UML_JMPc(block, COND_A, label);                             // ja      label4
-			// IOP registers
-			UML_MOV(block, mem(&m_core->arg0), I1);                     // mov     [m_core->arg0],i1
-			UML_CALLC(block, cfunc_read_iop, this);                     // callc   cfunc_read_iop
-			UML_MOV(block, I0, mem(&m_core->arg1));                     // mov     i0,[m_core->arg1]
-			UML_RET(block);
-
-			UML_LABEL(block, label++);                                  // label4:
-			UML_CMP(block, I1, IRAM_SHORT_BLOCK0_START);                // cmp     i1,IRAM_SHORT_BLOCK0_START
-			UML_JMPc(block, COND_B, label+1);                           // jb      label6
-			UML_CMP(block, I1, IRAM_SHORT_BLOCK0_END);                  // cmp     i1,IRAM_SHORT_BLOCK0_END
-			UML_JMPc(block, COND_A, label+1);                           // ja      label6
-			// 0x40000 ... 0x4ffff
-			UML_AND(block, I1, I1, 0xffff);                             // and     i1,i1,0xffff
-			UML_XOR(block, I1, I1, 1);                                  // xor     i1,i1,1
-			UML_TEST(block, mem(&m_core->mode1), 0x4000);               // test    [m_core->mode1],0x4000
-			UML_JMPc(block, COND_Z, label);                             // jz      label5
-			UML_LOADS(block, I0, block0, I1, SIZE_WORD, SCALE_x2);      // loads   i0,[block0],i1,word,scale_x2
-			UML_RET(block);
-			UML_LABEL(block, label++);                                  // label5:
-			UML_LOAD(block, I0, block0, I1, SIZE_WORD, SCALE_x2);       // load    i0,[block0],i1,word,scale_x2
-			UML_RET(block);
-
-			UML_LABEL(block, label++);                                  // label6:
-			UML_CMP(block, I1, IRAM_SHORT_BLOCK1_START);                // cmp     i1,IRAM_SHORT_BLOCK1_START
-			UML_JMPc(block, COND_B, label+1);                           // jb      label8
-			UML_CMP(block, I1, IRAM_SHORT_BLOCK1_END);                  // cmp     i1,IRAM_SHORT_BLOCK1_END
-			UML_JMPc(block, COND_A, label+1);                           // ja      label8
-			// 0x50000 ... 0x7ffff
-			UML_AND(block, I1, I1, 0xffff);                             // and     i1,i1,0xffff
-			UML_XOR(block, I1, I1, 1);                                  // xor     i1,i1,1
-			UML_TEST(block, mem(&m_core->mode1), 0x4000);               // test    [m_core->mode1],0x4000
-			UML_JMPc(block, COND_Z, label);                             // jz      label7
-			UML_LOADS(block, I0, block1, I1, SIZE_WORD, SCALE_x2);      // loads   i0,[block1],i1,word,scale_x2
-			UML_RET(block);
-			UML_LABEL(block, label++);                                  // label7:
-			UML_LOAD(block, I0, block1, I1, SIZE_WORD, SCALE_x2);       // load    i0,[block1],i1,word,scale_x2
-			UML_RET(block);
-
-			UML_LABEL(block, label++);                                  // label8:
+			UML_SHL(block, I1, I1, 2);
+			UML_READ(block, I0, I1, SIZE_DWORD, SPACE_DATA);
 			break;
 
 		case MEM_ACCESSOR_DM_WRITE32:
-#if WRITE_SNOOP
-			//UML_CMP(block, I1, 0x283eb);
-			UML_CMP(block, I1, 0x2400047);
-			UML_JMPc(block, COND_NE, label);
-			UML_MOV(block, mem(&m_core->arg0), I0);
-			UML_MOV(block, mem(&m_core->arg1), I1);
-			UML_MOV(block, mem(&m_core->arg2), mem(&m_core->pc));
-			UML_CALLC(block, cfunc_write_snoop, this);
-			UML_LABEL(block, label++);
-#endif
-
-
-			UML_CMP(block, I1, IRAM_END);                               // cmp     i1,IRAM_END
-			UML_JMPc(block, COND_BE, label);                            // jbe     label1
-			// 0x80000 ...
-			UML_SHL(block, I1, I1, 2);                                  // shl     i1,i1,2
-			UML_WRITE(block, I1, I0, SIZE_DWORD, SPACE_DATA);           // write   i1,i0,dword,SPACE_DATA
-			UML_RET(block);
-
-			UML_LABEL(block, label++);                                  // label1:
-			UML_CMP(block, I1, IRAM_BLOCK0_START);                      // cmp     i1,IRAM_BLOCK0_START
-			UML_JMPc(block, COND_B, label);                             // jb      label2
-			UML_CMP(block, I1, IRAM_BLOCK0_END);                        // cmp     i1,IRAM_BLOCK0_END
-			UML_JMPc(block, COND_A, label);                             // ja      label2
-			// 0x20000 ... 0x27fff
-			UML_AND(block, I1, I1, 0x7fff);                             // and     i1,i1,0x7fff
-			UML_STORE(block, block0_1, I1, I0, SIZE_WORD, SCALE_x4);    // store   [block0_1],i1,i0,word,scale_x4
-			UML_SHR(block, I0, I0, 16);                                 // shr     i0,i0,16
-			UML_STORE(block, block0, I1, I0, SIZE_WORD, SCALE_x4);      // store   [block0],i1,i0,word,scale_x4
-			UML_RET(block);
-
-			UML_LABEL(block, label++);                                  // label2:
-			UML_CMP(block, I1, IRAM_BLOCK1_START);                      // cmp     i1,IRAM_BLOCK1_START
-			UML_JMPc(block, COND_B, label);                             // jb      label3
-			UML_CMP(block, I1, IRAM_BLOCK1_END);                        // cmp     i1,IRAM_BLOCK1_END
-			UML_JMPc(block, COND_A, label);                             // ja      label3
-			// 0x28000 ... 0x3ffff
-			UML_AND(block, I1, I1, 0x7fff);                             // and     i1,i1,0x7fff
-			UML_STORE(block, block1_1, I1, I0, SIZE_WORD, SCALE_x4);    // store   [block1_1],i1,i0,word,scale_x4
-			UML_SHR(block, I0, I0, 16);                                 // shr     i0,i0,16
-			UML_STORE(block, block1, I1, I0, SIZE_WORD, SCALE_x4);      // store   [block1],i1,i0,word,scale_x4
-			UML_RET(block);
-
-			UML_LABEL(block, label++);                                  // Label3:
-			UML_CMP(block, I1, IOP_REGISTER_END);                       // cmp     i1,IOP_REGISTER_END
-			UML_JMPc(block, COND_A, label);                             // ja      label4
-			// IOP registers
-			UML_MOV(block, mem(&m_core->arg0), I1);                     // mov     [m_core->arg0],i1
-			UML_MOV(block, mem(&m_core->arg1), I0);                     // mov     [m_core->arg1],i0
-			UML_CALLC(block, cfunc_write_iop, this);                    // callc   cfunc_write_iop
-			UML_RET(block);
-
-			UML_LABEL(block, label++);                                  // label4:
-			UML_CMP(block, I1, IRAM_SHORT_BLOCK0_START);                // cmp     i1,IRAM_SHORT_BLOCK0_START
-			UML_JMPc(block, COND_B, label);                             // jb      label5
-			UML_CMP(block, I1, IRAM_SHORT_BLOCK0_END);                  // cmp     i1,IRAM_SHORT_BLOCK0_END
-			UML_JMPc(block, COND_A, label);                             // ja      label5
-			// 0x40000 ... 0x4ffff
-			UML_AND(block, I1, I1, 0xffff);                             // and     i1,i1,0xffff
-			UML_XOR(block, I1, I1, 1);                                  // xor     i1,i1,1
-			UML_STORE(block, block0, I1, I0, SIZE_WORD, SCALE_x2);      // store   [block0],i1,i0,word,scale_x2
-			UML_RET(block);
-
-			UML_LABEL(block, label++);                                  // label5:
-			UML_CMP(block, I1, IRAM_SHORT_BLOCK1_START);                // cmp     i1,IRAM_SHORT_BLOCK1_START
-			UML_JMPc(block, COND_B, label);                             // jb      label6
-			UML_CMP(block, I1, IRAM_SHORT_BLOCK1_END);                  // cmp     i1,IRAM_SHORT_BLOCK1_END
-			UML_JMPc(block, COND_A, label);                             // ja      label6
-			// 0x50000 ... 0x7ffff
-			UML_AND(block, I1, I1, 0xffff);                             // and     i1,i1,0xffff
-			UML_XOR(block, I1, I1, 1);                                  // xor     i1,i1,1
-			UML_STORE(block, block1, I1, I0, SIZE_WORD, SCALE_x2);      // store   [block1],i1,i0,word,scale_x2
-			UML_RET(block);
-
-			UML_LABEL(block, label++);                                  // label6:
+			UML_SHL(block, I1, I1, 2);
+			UML_WRITE(block, I1, I0, SIZE_DWORD, SPACE_DATA);
 			break;
 	}
 
diff --git a/src/devices/cpu/sharc/sharcmem.hxx b/src/devices/cpu/sharc/sharcmem.hxx
index d415fe0..b297799 100644
--- a/src/devices/cpu/sharc/sharcmem.hxx
+++ b/src/devices/cpu/sharc/sharcmem.hxx
@@ -4,201 +4,30 @@
 
 uint32_t adsp21062_device::pm_read32(uint32_t address)
 {
-	if (address >= 0x20000 && address < 0x28000)
-	{
-		uint32_t addr = (address & 0x7fff) * 3;
-
-		return (uint32_t)(m_internal_ram_block0[addr + 0] << 16) |
-						(m_internal_ram_block0[addr + 1]);
-	}
-	else if (address >= 0x28000 && address < 0x40000)
-	{
-		// block 1 is mirrored in 0x28000...2ffff, 0x30000...0x37fff and 0x38000...3ffff
-		uint32_t addr = (address & 0x7fff) * 3;
-
-		return (uint32_t)(m_internal_ram_block1[addr + 0] << 16) |
-						(m_internal_ram_block1[addr + 1]);
-	}
-	else {
-		fatalerror("SHARC: PM Bus Read32 %08X at %08X\n", address, m_core->pc);
-	}
+	return m_program->read_dword(address << 3);
 }
 
 void adsp21062_device::pm_write32(uint32_t address, uint32_t data)
 {
-	if (address >= 0x20000 && address < 0x28000)
-	{
-		uint32_t addr = (address & 0x7fff) * 3;
-
-		m_internal_ram_block0[addr + 0] = (uint16_t)(data >> 16);
-		m_internal_ram_block0[addr + 1] = (uint16_t)(data);
-		return;
-	}
-	else if (address >= 0x28000 && address < 0x40000)
-	{
-		// block 1 is mirrored in 0x28000...2ffff, 0x30000...0x37fff and 0x38000...3ffff
-		uint32_t addr = (address & 0x7fff) * 3;
-
-		m_internal_ram_block1[addr + 0] = (uint16_t)(data >> 16);
-		m_internal_ram_block1[addr + 1] = (uint16_t)(data);
-		return;
-	}
-	else {
-		fatalerror("SHARC: PM Bus Write32 %08X, %08X at %08X\n", address, data, m_core->pc);
-	}
+	m_program->write_dword(address << 3, data);
 }
 
 uint64_t adsp21062_device::pm_read48(uint32_t address)
 {
-	if ((address >= 0x20000 && address < 0x28000))
-	{
-		uint32_t addr = (address & 0x7fff) * 3;
-
-		return ((uint64_t)(m_internal_ram_block0[addr + 0]) << 32) |
-				((uint64_t)(m_internal_ram_block0[addr + 1]) << 16) |
-				((uint64_t)(m_internal_ram_block0[addr + 2]) << 0);
-	}
-	else if (address >= 0x28000 && address < 0x40000)
-	{
-		// block 1 is mirrored in 0x28000...2ffff, 0x30000...0x37fff and 0x38000...3ffff
-		uint32_t addr = (address & 0x7fff) * 3;
-
-		return ((uint64_t)(m_internal_ram_block1[addr + 0]) << 32) |
-				((uint64_t)(m_internal_ram_block1[addr + 1]) << 16) |
-				((uint64_t)(m_internal_ram_block1[addr + 2]) << 0);
-	}
-	else {
-		fatalerror("SHARC: PM Bus Read48 %08X at %08X\n", address, m_core->pc);
-	}
-
-	return 0;
+	return m_program->read_qword(address << 3);
 }
 
 void adsp21062_device::pm_write48(uint32_t address, uint64_t data)
 {
-	if ((address >= 0x20000 && address < 0x28000))
-	{
-		uint32_t addr = (address & 0x7fff) * 3;
-
-		m_internal_ram_block0[addr + 0] = (uint16_t)(data >> 32);
-		m_internal_ram_block0[addr + 1] = (uint16_t)(data >> 16);
-		m_internal_ram_block0[addr + 2] = (uint16_t)(data);
-		return;
-	}
-	else if (address >= 0x28000 && address < 0x40000)
-	{
-		// block 1 is mirrored in 0x28000...2ffff, 0x30000...0x37fff and 0x38000...3ffff
-		uint32_t addr = (address & 0x7fff) * 3;
-
-		m_internal_ram_block1[addr + 0] = (uint16_t)(data >> 32);
-		m_internal_ram_block1[addr + 1] = (uint16_t)(data >> 16);
-		m_internal_ram_block1[addr + 2] = (uint16_t)(data);
-		return;
-	}
-	else {
-		fatalerror("SHARC: PM Bus Write48 %08X, %04X%08X at %08X\n", address, (uint16_t)(data >> 32),(uint32_t)data, m_core->pc);
-	}
+	m_program->write_qword(address << 3, data);
 }
 
 uint32_t adsp21062_device::dm_read32(uint32_t address)
 {
-	if (address < 0x100)
-	{
-		return sharc_iop_r(address);
-	}
-	else if (address >= 0x20000 && address < 0x28000)
-	{
-		uint32_t addr = (address & 0x7fff) * 2;
-
-		return (uint32_t)(m_internal_ram_block0[addr + 0] << 16) |
-						(m_internal_ram_block0[addr + 1]);
-	}
-	else if (address >= 0x28000 && address < 0x40000)
-	{
-		// block 1 is mirrored in 0x28000...2ffff, 0x30000...0x37fff and 0x38000...3ffff
-		uint32_t addr = (address & 0x7fff) * 2;
-
-		return (uint32_t)(m_internal_ram_block1[addr + 0] << 16) |
-						(m_internal_ram_block1[addr + 1]);
-	}
-
-	// short word addressing
-	else if (address >= 0x40000 && address < 0x50000)
-	{
-		uint32_t addr = address & 0xffff;
-
-		uint16_t r = m_internal_ram_block0[addr ^ 1];
-		if (m_core->mode1 & 0x4000)
-		{
-			// sign-extend
-			return (int32_t)(int16_t)(r);
-		}
-		else
-		{
-			return (uint32_t)(r);
-		}
-	}
-	else if (address >= 0x50000 && address < 0x80000)
-	{
-		// block 1 is mirrored in 0x50000...5ffff, 0x60000...0x6ffff and 0x70000...7ffff
-		uint32_t addr = address & 0xffff;
-
-		uint16_t r = m_internal_ram_block1[addr ^ 1];
-		if (m_core->mode1 & 0x4000)
-		{
-			// sign-extend
-			return (int32_t)(int16_t)(r);
-		}
-		else
-		{
-			return (uint32_t)(r);
-		}
-	}
-
 	return m_data->read_dword(address << 2);
 }
 
 void adsp21062_device::dm_write32(uint32_t address, uint32_t data)
 {
-	if (address < 0x100)
-	{
-		sharc_iop_w(address, data);
-		return;
-	}
-	else if (address >= 0x20000 && address < 0x28000)
-	{
-		uint32_t addr = (address & 0x7fff) * 2;
-
-		m_internal_ram_block0[addr + 0] = (uint16_t)(data >> 16);
-		m_internal_ram_block0[addr + 1] = (uint16_t)(data);
-		return;
-	}
-	else if (address >= 0x28000 && address < 0x40000)
-	{
-		// block 1 is mirrored in 0x28000...2ffff, 0x30000...0x37fff and 0x38000...3ffff
-		uint32_t addr = (address & 0x7fff) * 2;
-
-		m_internal_ram_block1[addr + 0] = (uint16_t)(data >> 16);
-		m_internal_ram_block1[addr + 1] = (uint16_t)(data);
-		return;
-	}
-
-	// short word addressing
-	else if (address >= 0x40000 && address < 0x50000)
-	{
-		uint32_t addr = address & 0xffff;
-
-		m_internal_ram_block0[addr ^ 1] = data;
-		return;
-	}
-	else if (address >= 0x50000 && address < 0x80000)
-	{
-		// block 1 is mirrored in 0x50000...5ffff, 0x60000...0x6ffff and 0x70000...7ffff
-		uint32_t addr = address & 0xffff;
-
-		m_internal_ram_block1[addr ^ 1] = data;
-		return;
-	}
-
 	m_data->write_dword(address << 2, data);
 }
diff --git a/src/devices/cpu/tms32025/tms32025.cpp b/src/devices/cpu/tms32025/tms32025.cpp
index dc0e69e..5abbd29 100644
--- a/src/devices/cpu/tms32025/tms32025.cpp
+++ b/src/devices/cpu/tms32025/tms32025.cpp
@@ -126,25 +126,6 @@ Table 3-2.  TMS32025/26 Memory Blocks
 #define CLK 4   /* 1 cycle equals 4 clock ticks */      /* PE/DI */
 
 
-
-#define SET_PC(x)   do { m_PC = (x); } while (0)
-
-#define P_IN(A)         (m_io->read_word((A)<<1))
-#define P_OUT(A,V)      (m_io->write_word(((A)<<1),(V)))
-
-#define M_RDOP(A)       ((m_pgmmap[(A) >> 7]) ? (m_pgmmap[(A) >> 7][(A) & 0x7f]) : m_direct->read_word((A)<<1))
-#define M_RDOP_ARG(A)   ((m_pgmmap[(A) >> 7]) ? (m_pgmmap[(A) >> 7][(A) & 0x7f]) : m_direct->read_word((A)<<1))
-
-
-/************************** Memory mapped registers ****************/
-#define DRR     m_intRAM[0]
-#define DXR     m_intRAM[1]
-#define TIM     m_intRAM[2]
-#define PRD     m_intRAM[3]
-#define IMR     m_intRAM[4]
-#define GREG    m_intRAM[5]
-
-
 /****************************************************************************
  *******  The following is the Status (Flag) register 0 definition.  ********
 | 15 | 14 | 13 | 12 |  11 | 10 |   9  | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
@@ -205,12 +186,41 @@ Table 3-2.  TMS32025/26 Memory Blocks
 const device_type TMS32025 = &device_creator<tms32025_device>;
 const device_type TMS32026 = &device_creator<tms32026_device>;
 
+static ADDRESS_MAP_START( tms32025_data, AS_DATA, 16, tms32025_device )
+	AM_RANGE(0x0000, 0x0000) AM_READWRITE(drr_r, drr_w)
+	AM_RANGE(0x0001, 0x0001) AM_READWRITE(dxr_r, dxr_w)
+	AM_RANGE(0x0002, 0x0002) AM_READWRITE(tim_r, tim_w)
+	AM_RANGE(0x0003, 0x0003) AM_READWRITE(prd_r, prd_w)
+	AM_RANGE(0x0004, 0x0004) AM_READWRITE(imr_r, imr_w)
+	AM_RANGE(0x0005, 0x0005) AM_READWRITE(greg_r, greg_w)
+	AM_RANGE(0x0060, 0x007f) AM_RAM AM_SHARE("b2")
+	AM_RANGE(0x0200, 0x02ff) AM_RAM AM_SHARE("b0")
+	AM_RANGE(0x0300, 0x03ff) AM_RAM AM_SHARE("b1")
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( tms32026_data, AS_DATA, 16, tms32025_device )
+	AM_RANGE(0x0000, 0x0000) AM_READWRITE(drr_r, drr_w)
+	AM_RANGE(0x0001, 0x0001) AM_READWRITE(dxr_r, dxr_w)
+	AM_RANGE(0x0002, 0x0002) AM_READWRITE(tim_r, tim_w)
+	AM_RANGE(0x0003, 0x0003) AM_READWRITE(prd_r, prd_w)
+	AM_RANGE(0x0004, 0x0004) AM_READWRITE(imr_r, imr_w)
+	AM_RANGE(0x0005, 0x0005) AM_READWRITE(greg_r, greg_w)
+	AM_RANGE(0x0060, 0x007f) AM_RAM AM_SHARE("b2")
+	AM_RANGE(0x0200, 0x03ff) AM_RAM AM_SHARE("b0")
+	AM_RANGE(0x0400, 0x05ff) AM_RAM AM_SHARE("b1")
+	AM_RANGE(0x0600, 0x07ff) AM_RAM AM_SHARE("b3")
+ADDRESS_MAP_END
+
 
 tms32025_device::tms32025_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
 	: cpu_device(mconfig, TMS32025, "TMS32025", tag, owner, clock, "tms32025", __FILE__)
 	, m_program_config("program", ENDIANNESS_BIG, 16, 16, -1)
-	, m_data_config("data", ENDIANNESS_BIG, 16, 16, -1)
+	, m_data_config("data", ENDIANNESS_BIG, 16, 16, -1, ADDRESS_MAP_NAME(tms32025_data))
 	, m_io_config("io", ENDIANNESS_BIG, 16, 16, -1)
+	, m_b0(*this, "b0")
+	, m_b1(*this, "b1")
+	, m_b2(*this, "b2")
+	, m_b3(*this, "b3")
 	, m_bio_in(*this)
 	, m_hold_in(*this)
 	, m_hold_ack_out(*this)
@@ -221,11 +231,15 @@ tms32025_device::tms32025_device(const machine_config &mconfig, const char *tag,
 }
 
 
-tms32025_device::tms32025_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, uint32_t clock, const char *shortname, const char *source)
+tms32025_device::tms32025_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, uint32_t clock, const char *shortname, const char *source, address_map_constructor map)
 	: cpu_device(mconfig, type, name, tag, owner, clock, shortname, source)
 	, m_program_config("program", ENDIANNESS_BIG, 16, 16, -1)
-	, m_data_config("data", ENDIANNESS_BIG, 16, 16, -1)
+	, m_data_config("data", ENDIANNESS_BIG, 16, 16, -1, map)
 	, m_io_config("io", ENDIANNESS_BIG, 16, 16, -1)
+	, m_b0(*this, "b0")
+	, m_b1(*this, "b1")
+	, m_b2(*this, "b2")
+	, m_b3(*this, "b3")
 	, m_bio_in(*this)
 	, m_hold_in(*this)
 	, m_hold_ack_out(*this)
@@ -237,7 +251,7 @@ tms32025_device::tms32025_device(const machine_config &mconfig, device_type type
 
 
 tms32026_device::tms32026_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
-	: tms32025_device(mconfig, TMS32026, "TMS32026", tag, owner, clock, "tms32026", __FILE__)
+	: tms32025_device(mconfig, TMS32026, "TMS32026", tag, owner, clock, "tms32026", __FILE__, ADDRESS_MAP_NAME(tms32026_data))
 {
 }
 
@@ -248,6 +262,73 @@ offs_t tms32025_device::disasm_disassemble(std::ostream &stream, offs_t pc, cons
 	return CPU_DISASSEMBLE_NAME(tms32025)(this, stream, pc, oprom, opram, options);
 }
 
+READ16_MEMBER( tms32025_device::drr_r)
+{
+	return m_drr;
+}
+
+WRITE16_MEMBER(tms32025_device::drr_w)
+{
+	m_drr = data;
+}
+
+READ16_MEMBER( tms32025_device::dxr_r)
+{
+	return m_dxr;
+}
+
+WRITE16_MEMBER(tms32025_device::dxr_w)
+{
+	m_dxr = data;
+
+	if(TXM) {
+		if(FSM)
+			m_waiting_for_serial_frame = 1;
+		else
+			m_IFR |= 0x20;
+	}
+}
+
+READ16_MEMBER( tms32025_device::tim_r)
+{
+	return m_tim;
+}
+
+WRITE16_MEMBER(tms32025_device::tim_w)
+{
+	m_tim = data;
+}
+
+READ16_MEMBER( tms32025_device::prd_r)
+{
+	return m_prd;
+}
+
+WRITE16_MEMBER(tms32025_device::prd_w)
+{
+	m_prd = data;
+}
+
+READ16_MEMBER( tms32025_device::imr_r)
+{
+	return m_imr;
+}
+
+WRITE16_MEMBER(tms32025_device::imr_w)
+{
+	m_imr = data;
+}
+
+READ16_MEMBER( tms32025_device::greg_r)
+{
+	return m_greg;
+}
+
+WRITE16_MEMBER(tms32025_device::greg_w)
+{
+	m_greg = data;
+}
+
 
 void tms32025_device::CLR0(uint16_t flag) { m_STR0 &= ~flag; m_STR0 |= 0x0400; }
 void tms32025_device::SET0(uint16_t flag) { m_STR0 |=  flag; m_STR0 |= 0x0400; }
@@ -276,51 +357,6 @@ void tms32025_device::MODIFY_ARP(int data)
 	m_STR0 |= 0x0400;
 }
 
-uint16_t tms32025_device::M_RDROM(offs_t addr)
-{
-	uint16_t *ram;
-	addr &= 0xffff;
-	ram = m_pgmmap[addr >> 7];
-	if (ram) return ram[addr & 0x7f];
-	return m_program->read_word(addr << 1);
-}
-
-void tms32025_device::M_WRTROM(offs_t addr, uint16_t data)
-{
-	uint16_t *ram;
-	addr &= 0xffff;
-	ram = m_pgmmap[addr >> 7];
-	if (ram) { ram[addr & 0x7f] = data; }
-	else m_program->write_word(addr << 1, data);
-}
-
-uint16_t tms32025_device::M_RDRAM(offs_t addr)
-{
-	uint16_t *ram;
-	addr &= 0xffff;
-	ram = m_datamap[addr >> 7];
-	if (ram) return ram[addr & 0x7f];
-	return m_data->read_word(addr << 1);
-}
-
-void tms32025_device::M_WRTRAM(offs_t addr, uint16_t data)
-{
-	uint16_t *ram;
-	addr &= 0xffff;
-	ram = m_datamap[addr >> 7];
-	if (ram) {
-		ram[addr & 0x7f] = data;
-		if(addr == 1 && ram == m_intRAM && TXM) {
-			if(FSM)
-				m_waiting_for_serial_frame = 1;
-			else
-				m_IFR |= 0x20;
-		}
-	}
-	else m_data->write_word(addr << 1, data);
-}
-
-
 uint16_t tms32025_device::reverse_carry_add(uint16_t arg0, uint16_t arg1 )
 {
 	uint16_t result = 0;
@@ -480,7 +516,7 @@ void tms32025_device::GETDATA(int shift,int signext)
 		m_external_mem_access = 0;
 	}
 
-	m_ALU.d = (uint16_t)M_RDRAM(m_memaccess);
+	m_ALU.d = (uint16_t)m_data->read_word(m_memaccess << 1);
 	if (signext) m_ALU.d = (int16_t)m_ALU.d;
 	m_ALU.d <<= shift;
 
@@ -494,14 +530,14 @@ void tms32025_device::PUTDATA(uint16_t data)
 		if (m_memaccess >= 0x800) m_external_mem_access = 1;    /* Pause if hold pin is active */
 		else m_external_mem_access = 0;
 
-		M_WRTRAM(IND, data);
+		m_data->write_word(IND << 1, data);
 		MODIFY_AR_ARP();
 	}
 	else {
 		if (m_memaccess >= 0x800) m_external_mem_access = 1;    /* Pause if hold pin is active */
 		else m_external_mem_access = 0;
 
-		M_WRTRAM(DMA, data);
+		m_data->write_word(DMA << 1, data);
 	}
 }
 void tms32025_device::PUTDATA_SST(uint16_t data)
@@ -516,7 +552,7 @@ void tms32025_device::PUTDATA_SST(uint16_t data)
 		m_opcode.b.l &= 0xf7;                   /* Stop ARP changes */
 		MODIFY_AR_ARP();
 	}
-	M_WRTRAM(m_memaccess, data);
+	m_data->write_word(m_memaccess << 1, data);
 }
 
 
@@ -604,8 +640,8 @@ void tms32025_device::addt()
 void tms32025_device::adlk()
 {
 	m_oldacc.d = m_ACC.d;
-	if (SXM) m_ALU.d =  (int16_t)M_RDOP_ARG(m_PC);
-	else     m_ALU.d = (uint16_t)M_RDOP_ARG(m_PC);
+	if (SXM) m_ALU.d =  (int16_t)m_direct->read_word(m_PC << 1);
+	else     m_ALU.d = (uint16_t)m_direct->read_word(m_PC << 1);
 	m_PC++;
 	m_ALU.d <<= (m_opcode.b.h & 0xf);
 	m_ACC.d += m_ALU.d;
@@ -624,7 +660,7 @@ void tms32025_device::and_()
 void tms32025_device::andk()
 {
 	m_oldacc.d = m_ACC.d;
-	m_ALU.d = (uint16_t)M_RDOP_ARG(m_PC);
+	m_ALU.d = (uint16_t)m_direct->read_word(m_PC << 1);
 	m_PC++;
 	m_ALU.d <<= (m_opcode.b.h & 0xf);
 	m_ACC.d &= m_ALU.d;
@@ -639,52 +675,52 @@ void tms32025_device::apac()
 }
 void tms32025_device::br()
 {
-	SET_PC(M_RDOP_ARG(m_PC));
+	m_PC = m_direct->read_word(m_PC << 1);
 	MODIFY_AR_ARP();
 }
 void tms32025_device::bacc()
 {
-	SET_PC(m_ACC.w.l);
+	m_PC = m_ACC.w.l;
 }
 void tms32025_device::banz()
 {
-	if (m_AR[ARP]) SET_PC(M_RDOP_ARG(m_PC));
+	if (m_AR[ARP]) m_PC = m_direct->read_word(m_PC << 1);
 	else m_PC++ ;
 	MODIFY_AR_ARP();
 }
 void tms32025_device::bbnz()
 {
-	if (TC) SET_PC(M_RDOP_ARG(m_PC));
+	if (TC) m_PC = m_direct->read_word(m_PC << 1);
 	else m_PC++ ;
 	MODIFY_AR_ARP();
 }
 void tms32025_device::bbz()
 {
-	if (TC == 0) SET_PC(M_RDOP_ARG(m_PC));
+	if (TC == 0) m_PC = m_direct->read_word(m_PC << 1);
 	else m_PC++ ;
 	MODIFY_AR_ARP();
 }
 void tms32025_device::bc()
 {
-	if (CARRY) SET_PC(M_RDOP_ARG(m_PC));
+	if (CARRY) m_PC = m_direct->read_word(m_PC << 1);
 	else m_PC++ ;
 	MODIFY_AR_ARP();
 }
 void tms32025_device::bgez()
 {
-	if ( (int32_t)(m_ACC.d) >= 0 ) SET_PC(M_RDOP_ARG(m_PC));
+	if ( (int32_t)(m_ACC.d) >= 0 ) m_PC = m_direct->read_word(m_PC << 1);
 	else m_PC++ ;
 	MODIFY_AR_ARP();
 }
 void tms32025_device::bgz()
 {
-	if ( (int32_t)(m_ACC.d) > 0 ) SET_PC(M_RDOP_ARG(m_PC));
+	if ( (int32_t)(m_ACC.d) > 0 ) m_PC = m_direct->read_word(m_PC << 1);
 	else m_PC++ ;
 	MODIFY_AR_ARP();
 }
 void tms32025_device::bioz()
 {
-	if (m_bio_in() != CLEAR_LINE) SET_PC(M_RDOP_ARG(m_PC));
+	if (m_bio_in() != CLEAR_LINE) m_PC = m_direct->read_word(m_PC << 1);
 	else m_PC++ ;
 	MODIFY_AR_ARP();
 }
@@ -702,17 +738,17 @@ void tms32025_device::bitt()
 }
 void tms32025_device::blez()
 {
-	if ( (int32_t)(m_ACC.d) <= 0 ) SET_PC(M_RDOP_ARG(m_PC));
+	if ( (int32_t)(m_ACC.d) <= 0 ) m_PC = m_direct->read_word(m_PC << 1);
 	else m_PC++ ;
 	MODIFY_AR_ARP();
 }
 void tms32025_device::blkd()
 {                                       /** Fix cycle timing **/
 	if (m_init_load_addr) {
-		m_PFC = M_RDOP_ARG(m_PC);
+		m_PFC = m_direct->read_word(m_PC << 1);
 		m_PC++;
 	}
-	m_ALU.d = M_RDRAM(m_PFC);
+	m_ALU.d = m_data->read_word(m_PFC << 1);
 	PUTDATA(m_ALU.d);
 	m_PFC++;
 	m_tms32025_dec_cycles += (1*CLK);
@@ -720,29 +756,29 @@ void tms32025_device::blkd()
 void tms32025_device::blkp()
 {                                       /** Fix cycle timing **/
 	if (m_init_load_addr) {
-		m_PFC = M_RDOP_ARG(m_PC);
+		m_PFC = m_direct->read_word(m_PC << 1);
 		m_PC++;
 	}
-	m_ALU.d = M_RDROM(m_PFC);
+	m_ALU.d = m_direct->read_word(m_PFC << 1);
 	PUTDATA(m_ALU.d);
 	m_PFC++;
 	m_tms32025_dec_cycles += (2*CLK);
 }
 void tms32025_device::blz()
 {
-	if ( (int32_t)(m_ACC.d) <  0 ) SET_PC(M_RDOP_ARG(m_PC));
+	if ( (int32_t)(m_ACC.d) <  0 ) m_PC = m_direct->read_word(m_PC << 1);
 	else m_PC++ ;
 	MODIFY_AR_ARP();
 }
 void tms32025_device::bnc()
 {
-	if (CARRY == 0) SET_PC(M_RDOP_ARG(m_PC));
+	if (CARRY == 0) m_PC = m_direct->read_word(m_PC << 1);
 	else m_PC++ ;
 	MODIFY_AR_ARP();
 }
 void tms32025_device::bnv()
 {
-	if (OV == 0) SET_PC(M_RDOP_ARG(m_PC));
+	if (OV == 0) m_PC = m_direct->read_word(m_PC << 1);
 	else {
 		m_PC++ ;
 		CLR0(OV_FLAG);
@@ -751,14 +787,14 @@ void tms32025_device::bnv()
 }
 void tms32025_device::bnz()
 {
-	if (m_ACC.d != 0) SET_PC(M_RDOP_ARG(m_PC));
+	if (m_ACC.d != 0) m_PC = m_direct->read_word(m_PC << 1);
 	else m_PC++ ;
 	MODIFY_AR_ARP();
 }
 void tms32025_device::bv()
 {
 	if (OV) {
-		SET_PC(M_RDOP_ARG(m_PC));
+		m_PC = m_direct->read_word(m_PC << 1);
 		CLR0(OV_FLAG);
 	}
 	else m_PC++ ;
@@ -766,20 +802,20 @@ void tms32025_device::bv()
 }
 void tms32025_device::bz()
 {
-	if (m_ACC.d == 0) SET_PC(M_RDOP_ARG(m_PC));
+	if (m_ACC.d == 0) m_PC = m_direct->read_word(m_PC << 1);
 	else m_PC++ ;
 	MODIFY_AR_ARP();
 }
 void tms32025_device::cala()
 {
 	PUSH_STACK(m_PC);
-	SET_PC(m_ACC.w.l);
+	m_PC = m_ACC.w.l;
 }
 void tms32025_device::call()
 {
 	m_PC++ ;
 	PUSH_STACK(m_PC);
-	SET_PC(M_RDOP_ARG((m_PC - 1)));
+	m_PC = m_direct->read_word((m_PC - 1) << 1);
 	MODIFY_AR_ARP();
 }
 void tms32025_device::cmpl()
@@ -806,131 +842,73 @@ void tms32025_device::cmpr()
 }
 void tms32025_device::cnfd()  /** next two fetches need to use previous CNF value ! **/
 {
-	CLR1(CNF0_REG);
-	m_datamap[4] = &m_intRAM[0x200];            /* B0 */
-	m_datamap[5] = &m_intRAM[0x280];            /* B0 */
-	m_pgmmap[510] = nullptr;
-	m_pgmmap[511] = nullptr;
+	if(m_STR1 & CNF0_REG) {
+		m_program->unmap_readwrite(0xff00, 0xffff);
+		m_data->install_ram(0x0200, 0x02ff, m_b0);
+		CLR1(CNF0_REG);
+	}
 }
 void tms32025_device::cnfp()  /** next two fetches need to use previous CNF value ! **/
 {
-	SET1(CNF0_REG);
-	m_datamap[4] = nullptr;                        /* B0 */
-	m_datamap[5] = nullptr;                        /* B0 */
-	m_pgmmap[510] = &m_intRAM[0x200];
-	m_pgmmap[511] = &m_intRAM[0x280];
+	if(!(m_STR1 & CNF0_REG)) {
+		m_program->install_ram(0xff00, 0xffff, m_b0);
+		m_data->unmap_readwrite(0x0200, 0x02ff);
+		SET1(CNF0_REG);
+	}
 }
-void tms32025_device::conf()  /** Need to reconfigure the memory blocks */
+
+void tms32025_device::conf()
 {
-	switch (m_opcode.b.l & 3)
-	{
-		case 00:    CLR1(CNF1_REG); CLR1(CNF0_REG);
-					m_datamap[4] = &m_intRAM[0x200];    /* B0 */
-					m_datamap[5] = &m_intRAM[0x280];    /* B0 */
-					m_datamap[6] = &m_intRAM[0x300];    /* B0 */
-					m_datamap[7] = &m_intRAM[0x380];    /* B0 */
-					m_datamap[8] = &m_intRAM[0x400];    /* B1 */
-					m_datamap[9] = &m_intRAM[0x480];    /* B1 */
-					m_datamap[10] = &m_intRAM[0x500];   /* B1 */
-					m_datamap[11] = &m_intRAM[0x580];   /* B1 */
-					m_datamap[12] = &m_intRAM[0x600];   /* B3 */
-					m_datamap[13] = &m_intRAM[0x680];   /* B3 */
-					m_datamap[14] = &m_intRAM[0x700];   /* B3 */
-					m_datamap[15] = &m_intRAM[0x780];   /* B3 */
-					m_pgmmap[500] = nullptr;
-					m_pgmmap[501] = nullptr;
-					m_pgmmap[502] = nullptr;
-					m_pgmmap[503] = nullptr;
-					m_pgmmap[504] = nullptr;
-					m_pgmmap[505] = nullptr;
-					m_pgmmap[506] = nullptr;
-					m_pgmmap[507] = nullptr;
-					m_pgmmap[508] = nullptr;
-					m_pgmmap[509] = nullptr;
-					m_pgmmap[510] = nullptr;
-					m_pgmmap[511] = nullptr;
-					break;
+	// Disabled on tms32025
+}
 
-		case 01:    CLR1(CNF1_REG); SET1(CNF0_REG);
-					m_datamap[4] = nullptr;
-					m_datamap[5] = nullptr;
-					m_datamap[6] = nullptr;
-					m_datamap[7] = nullptr;
-					m_datamap[8] = &m_intRAM[0x400];    /* B1 */
-					m_datamap[9] = &m_intRAM[0x480];    /* B1 */
-					m_datamap[10] = &m_intRAM[0x500];   /* B1 */
-					m_datamap[11] = &m_intRAM[0x580];   /* B1 */
-					m_datamap[12] = &m_intRAM[0x600];   /* B3 */
-					m_datamap[13] = &m_intRAM[0x680];   /* B3 */
-					m_datamap[14] = &m_intRAM[0x700];   /* B3 */
-					m_datamap[15] = &m_intRAM[0x780];   /* B3 */
-					m_pgmmap[500] = &m_intRAM[0x200];   /* B0 */
-					m_pgmmap[501] = &m_intRAM[0x280];   /* B0 */
-					m_pgmmap[502] = &m_intRAM[0x300];   /* B0 */
-					m_pgmmap[503] = &m_intRAM[0x380];   /* B0 */
-					m_pgmmap[504] = nullptr;
-					m_pgmmap[505] = nullptr;
-					m_pgmmap[506] = nullptr;
-					m_pgmmap[507] = nullptr;
-					m_pgmmap[508] = nullptr;
-					m_pgmmap[509] = nullptr;
-					m_pgmmap[510] = nullptr;
-					m_pgmmap[511] = nullptr;
-					break;
+void tms32026_device::cnfd()
+{
+	// Disabled on tms32026
+}
 
-		case 02:    SET1(CNF1_REG); CLR1(CNF0_REG);
-					m_datamap[4] = nullptr;
-					m_datamap[5] = nullptr;
-					m_datamap[6] = nullptr;
-					m_datamap[7] = nullptr;
-					m_datamap[8] = nullptr;
-					m_datamap[9] = nullptr;
-					m_datamap[10] = nullptr;
-					m_datamap[11] = nullptr;
-					m_datamap[12] = &m_intRAM[0x600];   /* B3 */
-					m_datamap[13] = &m_intRAM[0x680];   /* B3 */
-					m_datamap[14] = &m_intRAM[0x700];   /* B3 */
-					m_datamap[15] = &m_intRAM[0x780];   /* B3 */
-					m_pgmmap[500] = &m_intRAM[0x200];   /* B0 */
-					m_pgmmap[501] = &m_intRAM[0x280];   /* B0 */
-					m_pgmmap[502] = &m_intRAM[0x300];   /* B0 */
-					m_pgmmap[503] = &m_intRAM[0x380];   /* B0 */
-					m_pgmmap[504] = &m_intRAM[0x400];   /* B1 */
-					m_pgmmap[505] = &m_intRAM[0x480];   /* B1 */
-					m_pgmmap[506] = &m_intRAM[0x500];   /* B1 */
-					m_pgmmap[507] = &m_intRAM[0x580];   /* B1 */
-					m_pgmmap[508] = nullptr;
-					m_pgmmap[509] = nullptr;
-					m_pgmmap[510] = nullptr;
-					m_pgmmap[511] = nullptr;
-					break;
+void tms32026_device::cnfp()
+{
+	// Disabled on tms32026
+}
 
-		case 03:    SET1(CNF1_REG); SET1(CNF0_REG);
-					m_datamap[4] = nullptr;
-					m_datamap[5] = nullptr;
-					m_datamap[6] = nullptr;
-					m_datamap[7] = nullptr;
-					m_datamap[8] = nullptr;
-					m_datamap[9] = nullptr;
-					m_datamap[10] = nullptr;
-					m_datamap[11] = nullptr;
-					m_datamap[12] = nullptr;
-					m_datamap[13] = nullptr;
-					m_datamap[14] = nullptr;
-					m_datamap[15] = nullptr;
-					m_pgmmap[500] = &m_intRAM[0x200];   /* B0 */
-					m_pgmmap[501] = &m_intRAM[0x280];   /* B0 */
-					m_pgmmap[502] = &m_intRAM[0x300];   /* B0 */
-					m_pgmmap[503] = &m_intRAM[0x380];   /* B0 */
-					m_pgmmap[504] = &m_intRAM[0x400];   /* B1 */
-					m_pgmmap[505] = &m_intRAM[0x480];   /* B1 */
-					m_pgmmap[506] = &m_intRAM[0x500];   /* B1 */
-					m_pgmmap[507] = &m_intRAM[0x580];   /* B1 */
-					m_pgmmap[508] = &m_intRAM[0x600];   /* B3 */
-					m_pgmmap[509] = &m_intRAM[0x680];   /* B3 */
-					m_pgmmap[510] = &m_intRAM[0x700];   /* B3 */
-					m_pgmmap[511] = &m_intRAM[0x780];   /* B3 */
-					break;
+void tms32026_device::conf()  /** Need to reconfigure the memory blocks */
+{
+	int prev = ((m_STR1 & CNF1_REG) ? 2 : 0) | ((m_STR1 & CNF0_REG) ? 1 : 0);
+	int next = m_opcode.b.l & 3;
+
+	if(next & 1)
+		SET1(CNF0_REG);
+	else
+		CLR1(CNF0_REG);
+
+	if(next & 2)
+		SET1(CNF1_REG);
+	else
+		CLR1(CNF1_REG);
+
+	if(next < 1 && prev >= 1) {
+		m_program->unmap_readwrite(0xfa00, 0xfbff);
+		m_data->install_ram(0x0200, 0x03ff, m_b0);
+	} else if(next < 1 && prev >= 1) {
+		m_program->install_ram(0xfa00, 0xfbff, m_b0);
+		m_data->unmap_readwrite(0x0200, 0x03ff);
+	}
+
+	if(next < 2 && prev >= 2) {
+		m_program->unmap_readwrite(0xfc00, 0xfdff);
+		m_data->install_ram(0x0400, 0x05ff, m_b1);
+	} else if(next < 2 && prev >= 2) {
+		m_program->install_ram(0xfc00, 0xfdff, m_b1);
+		m_data->unmap_readwrite(0x0400, 0x05ff);
+	}
+
+	if(next < 3 && prev >= 3) {
+		m_program->unmap_readwrite(0xfe00, 0xffff);
+		m_data->install_ram(0x0600, 0x07ff, m_b3);
+	} else if(next < 3 && prev >= 3) {
+		m_program->install_ram(0xfe00, 0xffff, m_b3);
+		m_data->unmap_readwrite(0x0600, 0x07ff);
 	}
 }
 void tms32025_device::dint()
@@ -940,7 +918,7 @@ void tms32025_device::dint()
 void tms32025_device::dmov()  /** Careful with how memory is configured !! */
 {
 	GETDATA(0, 0);
-	M_WRTRAM((m_memaccess + 1), m_ALU.w.l);
+	m_data->write_word((m_memaccess + 1) << 1, m_ALU.w.l);
 }
 void tms32025_device::eint()
 {
@@ -958,7 +936,7 @@ void tms32025_device::idle()
 }
 void tms32025_device::in()
 {
-	m_ALU.w.l = P_IN( (m_opcode.b.h & 0xf) );
+	m_ALU.w.l = m_io->read_word( (m_opcode.b.h & 0xf) << 1 );
 	PUTDATA(m_ALU.w.l);
 }
 void tms32025_device::lac()
@@ -977,8 +955,8 @@ void tms32025_device::lact()
 }
 void tms32025_device::lalk()
 {
-	if (SXM) m_ALU.d =  (int16_t)M_RDOP_ARG(m_PC);
-	else     m_ALU.d = (uint16_t)M_RDOP_ARG(m_PC);
+	if (SXM) m_ALU.d =  (int16_t)m_direct->read_word(m_PC << 1);
+	else     m_ALU.d = (uint16_t)m_direct->read_word(m_PC << 1);
 	m_PC++;
 	m_ALU.d <<= (m_opcode.b.h & 0xf);
 	m_ACC.d = m_ALU.d;
@@ -1015,7 +993,7 @@ void tms32025_device::lph()
 }
 void tms32025_device::lrlk()
 {
-	m_ALU.d = (uint16_t)M_RDOP_ARG(m_PC);
+	m_ALU.d = (uint16_t)m_direct->read_word(m_PC << 1);
 	m_PC++;
 	m_AR[m_opcode.b.h & 7] = m_ALU.w.l;
 }
@@ -1061,7 +1039,7 @@ void tms32025_device::ltd()   /** Careful with how memory is configured !! */
 	m_oldacc.d = m_ACC.d;
 	GETDATA(0, 0);
 	m_Treg = m_ALU.w.l;
-	M_WRTRAM((m_memaccess+1), m_ALU.w.l);
+	m_data->write_word((m_memaccess+1) << 1, m_ALU.w.l);
 	SHIFT_Preg_TO_ALU();
 	m_ACC.d += m_ALU.d;
 	CALCULATE_ADD_OVERFLOW(m_ALU.d);
@@ -1089,7 +1067,7 @@ void tms32025_device::mac()           /** RAM blocks B0,B1,B2 may be important !
 {                               /** Fix cycle timing **/
 	m_oldacc.d = m_ACC.d;
 	if (m_init_load_addr) {
-		m_PFC = M_RDOP_ARG(m_PC);
+		m_PFC = m_direct->read_word(m_PC << 1);
 		m_PC++;
 	}
 	SHIFT_Preg_TO_ALU();
@@ -1098,7 +1076,7 @@ void tms32025_device::mac()           /** RAM blocks B0,B1,B2 may be important !
 	CALCULATE_ADD_CARRY();
 	GETDATA(0, 0);
 	m_Treg = m_ALU.w.l;
-	m_Preg.d = ( (int16_t)m_ALU.w.l * (int16_t)M_RDROM(m_PFC) );
+	m_Preg.d = ( (int16_t)m_ALU.w.l * (int16_t)m_direct->read_word(m_PFC << 1) );
 	m_PFC++;
 	m_tms32025_dec_cycles += (2*CLK);
 }
@@ -1106,7 +1084,7 @@ void tms32025_device::macd()          /** RAM blocks B0,B1,B2 may be important !
 {                                                   /** Fix cycle timing **/
 	m_oldacc.d = m_ACC.d;
 	if (m_init_load_addr) {
-		m_PFC = M_RDOP_ARG(m_PC);
+		m_PFC = m_direct->read_word(m_PC << 1);
 		m_PC++;
 	}
 	SHIFT_Preg_TO_ALU();
@@ -1115,10 +1093,10 @@ void tms32025_device::macd()          /** RAM blocks B0,B1,B2 may be important !
 	CALCULATE_ADD_CARRY();
 	GETDATA(0, 0);
 	if ( (m_opcode.b.l & 0x80) || m_init_load_addr ) {  /* No writing during repetition, or DMA mode */
-		M_WRTRAM((m_memaccess+1), m_ALU.w.l);
+		m_data->write_word((m_memaccess+1) << 1, m_ALU.w.l);
 	}
 	m_Treg = m_ALU.w.l;
-	m_Preg.d = ( (int16_t)m_ALU.w.l * (int16_t)M_RDROM(m_PFC) );
+	m_Preg.d = ( (int16_t)m_ALU.w.l * (int16_t)m_direct->read_word(m_PFC << 1) );
 	m_PFC++;
 	m_tms32025_dec_cycles += (2*CLK);
 }
@@ -1191,7 +1169,7 @@ void tms32025_device::or_()
 }
 void tms32025_device::ork()
 {
-	m_ALU.d = (uint16_t)M_RDOP_ARG(m_PC);
+	m_ALU.d = (uint16_t)m_direct->read_word(m_PC << 1);
 	m_PC++;
 	m_ALU.d <<= (m_opcode.b.h & 0xf);
 	m_ACC.d |=  (m_ALU.d);
@@ -1199,7 +1177,7 @@ void tms32025_device::ork()
 void tms32025_device::out()
 {
 	GETDATA(0, 0);
-	P_OUT( (m_opcode.b.h & 0xf), m_ALU.w.l );
+	m_io->write_word( (m_opcode.b.h & 0xf) << 1, m_ALU.w.l );
 }
 void tms32025_device::pac()
 {
@@ -1230,7 +1208,7 @@ void tms32025_device::rc()
 }
 void tms32025_device::ret()
 {
-	SET_PC(POP_STACK());
+	m_PC = POP_STACK();
 }
 void tms32025_device::rfsm()              /** serial port mode */
 {
@@ -1310,8 +1288,8 @@ void tms32025_device::sar_ar7()   { PUTDATA(m_AR[7]); }
 void tms32025_device::sblk()
 {
 	m_oldacc.d = m_ACC.d;
-	if (SXM) m_ALU.d =  (int16_t)M_RDOP_ARG(m_PC);
-	else     m_ALU.d = (uint16_t)M_RDOP_ARG(m_PC);
+	if (SXM) m_ALU.d =  (int16_t)m_direct->read_word(m_PC << 1);
+	else     m_ALU.d = (uint16_t)m_direct->read_word(m_PC << 1);
 	m_PC++;
 	m_ALU.d <<= (m_opcode.b.h & 0xf);
 	m_ACC.d -= m_ALU.d;
@@ -1502,7 +1480,7 @@ void tms32025_device::tblr()
 	if (m_init_load_addr) {
 		m_PFC = m_ACC.w.l;
 	}
-	m_ALU.w.l = M_RDROM(m_PFC);
+	m_ALU.w.l = m_direct->read_word(m_PFC << 1);
 	if ( (CNF0) && ( (uint16_t)(m_PFC) >= 0xff00 ) ) {}   /** TMS32025 only */
 	else m_tms32025_dec_cycles += (1*CLK);
 	PUTDATA(m_ALU.w.l);
@@ -1516,13 +1494,13 @@ void tms32025_device::tblw()
 	m_tms32025_dec_cycles += (1*CLK);
 	GETDATA(0, 0);
 	if (m_external_mem_access) m_tms32025_dec_cycles += (1*CLK);
-	M_WRTROM(m_PFC, m_ALU.w.l);
+	m_program->write_word(m_PFC << 1, m_ALU.w.l);
 	m_PFC++;
 }
 void tms32025_device::trap()
 {
 	PUSH_STACK(m_PC);
-	SET_PC(0x001E);     /* Trap vector */
+	m_PC = 0x001E;     /* Trap vector */
 }
 void tms32025_device::xor_()
 {
@@ -1531,7 +1509,7 @@ void tms32025_device::xor_()
 }
 void tms32025_device::xork()
 {
-	m_ALU.d = M_RDOP_ARG(m_PC);
+	m_ALU.d = m_direct->read_word(m_PC << 1);
 	m_PC++;
 	m_ALU.d <<= (m_opcode.b.h & 0xf);
 	m_ACC.d ^= m_ALU.d;
@@ -1666,7 +1644,8 @@ void tms32025_device::device_start()
 	m_AR[0] = m_AR[1] = m_AR[2] = m_AR[3] = m_AR[4] = m_AR[5] = m_AR[6] = m_AR[7] = 0;
 	m_STACK[0] = m_STACK[1] = m_STACK[2] = m_STACK[3] = m_STACK[4] = m_STACK[5] = m_STACK[6] = m_STACK[7] = 0;
 	m_ALU.d = 0;
-	memset(m_intRAM, 0, sizeof(m_intRAM));
+	m_drr = 0;
+	m_dxr = 0;
 	m_timerover = 0;
 	m_opcode.d = 0;
 	m_external_mem_access = 0;
@@ -1713,8 +1692,6 @@ void tms32025_device::device_start()
 	save_item(NAME(m_init_load_addr));
 	save_item(NAME(m_PREVPC));
 
-	save_item(NAME(m_intRAM));
-
 	state_add( TMS32025_PC,   "PC",   m_PC).formatstr("%04X");
 	state_add( TMS32025_STR0, "STR0", m_STR0).formatstr("%04X");
 	state_add( TMS32025_STR1, "STR1", m_STR1).formatstr("%04X");
@@ -1739,12 +1716,12 @@ void tms32025_device::device_start()
 	state_add( TMS32025_AR5,  "AR5",  m_AR[5]).formatstr("%04X");
 	state_add( TMS32025_AR6,  "AR6",  m_AR[6]).formatstr("%04X");
 	state_add( TMS32025_AR7,  "AR7",  m_AR[7]).formatstr("%04X");
-	state_add( TMS32025_DRR,  "DRR",  m_debugger_temp).callimport().callexport().formatstr("%04X");
-	state_add( TMS32025_DXR,  "DXR",  m_debugger_temp).callimport().callexport().formatstr("%04X");
-	state_add( TMS32025_TIM,  "TIM",  m_debugger_temp).callimport().callexport().formatstr("%04X");
-	state_add( TMS32025_PRD,  "PRD",  m_debugger_temp).callimport().callexport().formatstr("%04X");
-	state_add( TMS32025_IMR,  "IMR",  m_debugger_temp).callimport().callexport().formatstr("%04X");
-	state_add( TMS32025_GREG, "GREG", m_debugger_temp).callimport().callexport().formatstr("%04X");
+	state_add( TMS32025_DRR,  "DRR",  m_drr).formatstr("%04X");
+	state_add( TMS32025_DXR,  "DXR",  m_dxr).formatstr("%04X");
+	state_add( TMS32025_TIM,  "TIM",  m_tim).formatstr("%04X");
+	state_add( TMS32025_PRD,  "PRD",  m_prd).formatstr("%04X");
+	state_add( TMS32025_IMR,  "IMR",  m_imr).formatstr("%04X");
+	state_add( TMS32025_GREG, "GREG", m_greg).formatstr("%04X");
 
 	state_add(STATE_GENPC, "GENPC", m_PC).formatstr("%04X").noshow();
 	state_add(STATE_GENPCBASE, "CURPC", m_PREVPC).formatstr("%04X").noshow();
@@ -1756,68 +1733,6 @@ void tms32025_device::device_start()
 }
 
 
-void tms32025_device::state_import(const device_state_entry &entry)
-{
-	switch (entry.index())
-	{
-		case TMS32025_DRR:
-			M_WRTRAM(0, m_debugger_temp);
-			break;
-
-		case TMS32025_DXR:
-			M_WRTRAM(1, m_debugger_temp);
-			break;
-
-		case TMS32025_TIM:
-			M_WRTRAM(2, m_debugger_temp);
-			break;
-
-		case TMS32025_PRD:
-			M_WRTRAM(3, m_debugger_temp);
-			break;
-
-		case TMS32025_IMR:
-			M_WRTRAM(4,m_debugger_temp);
-			break;
-
-		case TMS32025_GREG:
-			M_WRTRAM(5, m_debugger_temp);
-			break;
-	}
-}
-
-
-void tms32025_device::state_export(const device_state_entry &entry)
-{
-	switch (entry.index())
-	{
-		case TMS32025_DRR:
-			m_debugger_temp = M_RDRAM(0);
-			break;
-
-		case TMS32025_DXR:
-			m_debugger_temp = M_RDRAM(1);
-			break;
-
-		case TMS32025_TIM:
-			m_debugger_temp = M_RDRAM(2);
-			break;
-
-		case TMS32025_PRD:
-			m_debugger_temp = M_RDRAM(3);
-			break;
-
-		case TMS32025_IMR:
-			m_debugger_temp = M_RDRAM(4);
-			break;
-
-		case TMS32025_GREG:
-			m_debugger_temp = M_RDRAM(5);
-			break;
-	}
-}
-
-
 void tms32025_device::state_string_export(const device_state_entry &entry, std::string &str) const
 {
 	switch (entry.index())
@@ -1853,9 +1768,9 @@ void tms32025_device::state_string_export(const device_state_entry &entry, std::
 /****************************************************************************
  *  Reset registers to their initial values
  ****************************************************************************/
-void tms32025_device::device_reset()
+void tms32025_device::common_reset()
 {
-	SET_PC(0);                  /* Starting address on a reset */
+	m_PC = 0;           /* Starting address on a reset */
 	m_STR0 |= 0x0600;   /* INTM and unused bit set to 1 */
 	m_STR0 &= 0xefff;   /* OV cleared to 0. Remaining bits undefined */
 	m_STR1 |= 0x07f0;   /* SXM, C, HM, FSM, XF and unused bits set to 1 */
@@ -1865,40 +1780,30 @@ void tms32025_device::device_reset()
 
 	m_xf_out(ASSERT_LINE); /* XF flag is high. Must set the pin */
 
-	/* Set the internal memory mapped registers */
-	GREG = 0;
-	TIM  = 0xffff;
-	PRD  = 0xffff;
-	IMR  = 0xffc0;
+	m_greg = 0;
+	m_tim  = 0xffff;
+	m_prd  = 0xffff;
+	m_imr  = 0xffc0;
 
 	m_idle = 0;
 	m_hold = 0;
 	m_tms32025_dec_cycles = 0;
 	m_init_load_addr = 1;
+}
 
-	/* Reset the Data/Program address banks */
-	memset(m_pgmmap, 0, sizeof(m_pgmmap));
-	memset(m_datamap, 0, sizeof(m_datamap));
+void tms32025_device::device_reset()
+{
+	if(m_STR1 & CNF0_REG) {
+		m_program->unmap_readwrite(0xff00, 0xffff);
+		m_data->install_ram(0x0200, 0x02ff, m_b0);
+	}
+	common_reset();
 
-	m_datamap[0] = &m_intRAM[0x000];            /* B2 */
-	m_datamap[4] = &m_intRAM[0x200];            /* B0 */
-	m_datamap[5] = &m_intRAM[0x280];            /* B0 */
-	m_datamap[6] = &m_intRAM[0x300];            /* B1 */
-	m_datamap[7] = &m_intRAM[0x380];            /* B1 */
 }
 
 void tms32026_device::device_reset()
 {
-	tms32025_device::device_reset();
-
-	m_datamap[8] = &m_intRAM[0x400];            /* B1 */
-	m_datamap[9] = &m_intRAM[0x480];            /* B1 */
-	m_datamap[10] = &m_intRAM[0x500];           /* B1 */
-	m_datamap[11] = &m_intRAM[0x580];           /* B1 */
-	m_datamap[12] = &m_intRAM[0x600];           /* B3 */
-	m_datamap[13] = &m_intRAM[0x680];           /* B3 */
-	m_datamap[14] = &m_intRAM[0x700];           /* B3 */
-	m_datamap[15] = &m_intRAM[0x780];           /* B3 */
+	common_reset();
 }
 
 
@@ -1916,59 +1821,59 @@ int tms32025_device::process_IRQs()
 
 	/* Dont service Interrupts if masked, or prev instruction was EINT ! */
 
-	if ( (INTM == 0) && (m_opcode.w.l != 0xce00) && (m_IFR & IMR) )
+	if ( (INTM == 0) && (m_opcode.w.l != 0xce00) && (m_IFR & m_imr) )
 	{
 		m_tms32025_irq_cycles = (3*CLK);    /* 3 clock cycles used due to PUSH and DINT operation ? */
 		PUSH_STACK(m_PC);
 
-		if ((m_IFR & 0x01) && (IMR & 0x01)) {       /* IRQ line 0 */
+		if ((m_IFR & 0x01) && (m_imr & 0x01)) {       /* IRQ line 0 */
 			//logerror("TMS32025:  Active INT0\n");
-			SET_PC(0x0002);
+			m_PC = 0x0002;
 			standard_irq_callback(0);
 			m_idle = 0;
 			m_IFR &= (~0x01);
 			SET0(INTM_FLAG);
 			return m_tms32025_irq_cycles;
 		}
-		if ((m_IFR & 0x02) && (IMR & 0x02)) {       /* IRQ line 1 */
+		if ((m_IFR & 0x02) && (m_imr & 0x02)) {       /* IRQ line 1 */
 			//logerror("TMS32025:  Active INT1\n");
-			SET_PC(0x0004);
+			m_PC = 0x0004;
 			standard_irq_callback(1);
 			m_idle = 0;
 			m_IFR &= (~0x02);
 			SET0(INTM_FLAG);
 			return m_tms32025_irq_cycles;
 		}
-		if ((m_IFR & 0x04) && (IMR & 0x04)) {       /* IRQ line 2 */
+		if ((m_IFR & 0x04) && (m_imr & 0x04)) {       /* IRQ line 2 */
 			//logerror("TMS32025:  Active INT2\n");
-			SET_PC(0x0006);
+			m_PC = 0x0006;
 			standard_irq_callback(2);
 			m_idle = 0;
 			m_IFR &= (~0x04);
 			SET0(INTM_FLAG);
 			return m_tms32025_irq_cycles;
 		}
-		if ((m_IFR & 0x08) && (IMR & 0x08)) {       /* Timer IRQ (internal) */
+		if ((m_IFR & 0x08) && (m_imr & 0x08)) {       /* Timer IRQ (internal) */
 //          logerror("TMS32025:  Active TINT (Timer)\n");
-			SET_PC(0x0018);
+			m_PC = 0x0018;
 			m_idle = 0;
 			m_IFR &= (~0x08);
 			SET0(INTM_FLAG);
 			return m_tms32025_irq_cycles;
 		}
-		if ((m_IFR & 0x10) && (IMR & 0x10)) {       /* Serial port receive IRQ (internal) */
+		if ((m_IFR & 0x10) && (m_imr & 0x10)) {       /* Serial port receive IRQ (internal) */
 //          logerror("TMS32025:  Active RINT (Serial receive)\n");
-			DRR = m_dr_in();
-			SET_PC(0x001A);
+			m_drr = m_dr_in();
+			m_PC = 0x001A;
 			m_idle = 0;
 			m_IFR &= (~0x10);
 			SET0(INTM_FLAG);
 			return m_tms32025_irq_cycles;
 		}
-		if ((m_IFR & 0x20) && (IMR & 0x20)) {       /* Serial port transmit IRQ (internal) */
+		if ((m_IFR & 0x20) && (m_imr & 0x20)) {       /* Serial port transmit IRQ (internal) */
 //          logerror("TMS32025:  Active XINT (Serial transmit)\n");
-			m_dx_out(DXR);
-			SET_PC(0x001C);
+			m_dx_out(m_dxr);
+			m_PC = 0x001C;
 			m_idle = 0;
 			m_IFR &= (~0x20);
 			SET0(INTM_FLAG);
@@ -1995,19 +1900,19 @@ again:
 
 	/* if we're not going to overflow the timer, just count the clocks */
 	ticks = 1 + (clocks - preclocks) / CLK;
-	if (ticks <= TIM)
+	if (ticks <= m_tim)
 	{
 		m_icount -= clocks;
 		m_timerover = clocks - (ticks - 1) * CLK - preclocks;
-		TIM -= ticks;
+		m_tim -= ticks;
 	}
 
 	/* otherwise, overflow the timer and signal an interrupt */
 	else
 	{
-		m_icount -= preclocks + CLK * TIM;
+		m_icount -= preclocks + CLK * m_tim;
 		m_timerover = 0;
-		TIM = PRD;
+		m_tim = m_prd;
 
 		m_IFR |= 0x08;
 		clocks = process_IRQs();        /* Handle Timer IRQ */
@@ -2066,7 +1971,7 @@ void tms32025_device::execute_run()
 
 		debugger_instruction_hook(this, m_PC);
 
-		m_opcode.d = M_RDOP(m_PC);
+		m_opcode.d = m_direct->read_word(m_PC << 1);
 		m_PC++;
 
 		if (m_opcode.b.h == 0xCE)   /* Opcode 0xCExx has many sub-opcodes in its minor byte */
@@ -2100,7 +2005,7 @@ void tms32025_device::execute_run()
 
 			debugger_instruction_hook(this, m_PC);
 
-			m_opcode.d = M_RDOP(m_PC);
+			m_opcode.d = m_direct->read_word(m_PC << 1);
 			m_PC++;
 			m_tms32025_dec_cycles += (1*CLK);
 
@@ -2174,126 +2079,3 @@ void tms32025_device::execute_set_input(int irqline, int state)
 		}
 	}
 }
-
-
-/****************************************************************************
- *  Opcode fetcher
- ****************************************************************************/
-bool tms32025_device::memory_readop(offs_t offset, int size, uint64_t &value)
-{
-	void *ptr;
-
-	/* skip if not custom */
-	if (!m_pgmmap[offset >> 8])
-		return 0;
-
-	ptr = &((uint8_t *)&m_pgmmap[offset >> 8])[offset & 0xff];
-	switch (size)
-	{
-		case 1: value = *((uint8_t *) ptr);
-		case 2: value = *((uint16_t *) ptr);
-		case 4: value = *((uint32_t *) ptr);
-		case 8: value = *((uint64_t *) ptr);
-	}
-	return 1;
-}
-
-
-/****************************************************************************
- *  Memory reader
- ****************************************************************************/
-bool tms32025_device::memory_read(address_spacenum spacenum, offs_t offset, int size, uint64_t &value)
-{
-	void *ptr;
-	uint64_t temp = 0;
-
-	switch (spacenum)
-	{
-		case AS_PROGRAM:
-			ptr = m_pgmmap[offset >> 8];
-			if (!ptr)
-				return 0;
-			break;
-
-		case AS_DATA:
-			ptr = m_datamap[offset >> 8];
-			if (!ptr)
-				return 0;
-			break;
-
-		default:
-		case AS_IO:
-			return 0;
-	}
-
-	switch (size)
-	{
-		case 1:
-			value = ((uint8_t *)ptr)[BYTE_XOR_BE(offset & 0xff)];
-			break;
-		case 2:
-			value = ((uint16_t *)ptr)[(offset & 0xff) / 2];
-			break;
-		case 4:
-			memory_read(spacenum, offset + 0, 2, temp);
-			value = temp << 16;
-			memory_read(spacenum, offset + 2, 2, temp);
-			value |= temp & 0xffff;
-			break;
-		case 8:
-			memory_read(spacenum, offset + 0, 4, temp);
-			value = temp << 32;
-			memory_read(spacenum, offset + 4, 4, temp);
-			value |= temp & 0xffffffff;
-			break;
-	}
-	return 1;
-}
-
-
-/****************************************************************************
- *  Memory writer
- ****************************************************************************/
-bool tms32025_device::memory_write(address_spacenum spacenum, offs_t offset, int size, uint64_t value)
-{
-	void *ptr;
-
-	switch (spacenum)
-	{
-		case AS_PROGRAM:
-			ptr = m_pgmmap[offset >> 8];
-			if (!ptr)
-				return 0;
-			break;
-
-		case AS_DATA:
-			ptr = m_datamap[offset >> 8];
-			if (!ptr)
-				return 0;
-			break;
-
-		default:
-		case AS_IO:
-			return 0;
-	}
-
-	switch (size)
-	{
-		case 1:
-			((uint8_t *)ptr)[BYTE_XOR_BE(offset & 0xff)] = value;
-			break;
-		case 2:
-			((uint16_t *)ptr)[(offset & 0xff) / 2] = value;
-			break;
-		case 4:
-			memory_write(spacenum, offset + 0, 2, value >> 16);
-			memory_write(spacenum, offset + 2, 2, value);
-			break;
-		case 8:
-			memory_write(spacenum, offset + 0, 4, value >> 32);
-			memory_write(spacenum, offset + 4, 4, value);
-			break;
-	}
-
-	return 1;
-}
diff --git a/src/devices/cpu/tms32025/tms32025.h b/src/devices/cpu/tms32025/tms32025.h
index bd752d5..61acec9 100644
--- a/src/devices/cpu/tms32025/tms32025.h
+++ b/src/devices/cpu/tms32025/tms32025.h
@@ -82,7 +82,7 @@ class tms32025_device : public cpu_device
 public:
 	// construction/destruction
 	tms32025_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-	tms32025_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, uint32_t clock, const char *shortname, const char *source);
+	tms32025_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, uint32_t clock, const char *shortname, const char *source, address_map_constructor map);
 
 	// static configuration helpers
 	template<class _Object> static devcb_base & set_bio_in_cb(device_t &device, _Object object) { return downcast<tms32025_device &>(device).m_bio_in.set_callback(object); }
@@ -92,6 +92,19 @@ public:
 	template<class _Object> static devcb_base & set_dr_in_cb(device_t &device, _Object object) { return downcast<tms32025_device &>(device).m_dr_in.set_callback(object); }
 	template<class _Object> static devcb_base & set_dx_out_cb(device_t &device, _Object object) { return downcast<tms32025_device &>(device).m_dx_out.set_callback(object); }
 
+	DECLARE_READ16_MEMBER( drr_r);
+	DECLARE_WRITE16_MEMBER(drr_w);
+	DECLARE_READ16_MEMBER( dxr_r);
+	DECLARE_WRITE16_MEMBER(dxr_w);
+	DECLARE_READ16_MEMBER( tim_r);
+	DECLARE_WRITE16_MEMBER(tim_w);
+	DECLARE_READ16_MEMBER( prd_r);
+	DECLARE_WRITE16_MEMBER(prd_w);
+	DECLARE_READ16_MEMBER( imr_r);
+	DECLARE_WRITE16_MEMBER(imr_w);
+	DECLARE_READ16_MEMBER( greg_r);
+	DECLARE_WRITE16_MEMBER(greg_w);
+
 protected:
 	// device-level overrides
 	virtual void device_start() override;
@@ -106,13 +119,8 @@ protected:
 
 	// device_memory_interface overrides
 	virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const override { return (spacenum == AS_PROGRAM) ? &m_program_config : ( (spacenum == AS_IO) ? &m_io_config : ( (spacenum == AS_DATA) ? &m_data_config : nullptr ) ); }
-	virtual bool memory_read(address_spacenum spacenum, offs_t offset, int size, uint64_t &value) override;
-	virtual bool memory_write(address_spacenum spacenum, offs_t offset, int size, uint64_t value) override;
-	virtual bool memory_readop(offs_t offset, int size, uint64_t &value) override;
 
 	// device_state_interface overrides
-	virtual void state_import(const device_state_entry &entry) override;
-	virtual void state_export(const device_state_entry &entry) override;
 	virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
 
 	// device_disasm_interface overrides
@@ -120,11 +128,22 @@ protected:
 	virtual uint32_t disasm_max_opcode_bytes() const override { return 4; }
 	virtual offs_t disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) override;
 
-private:
+	void common_reset();
+
 	address_space_config m_program_config;
 	address_space_config m_data_config;
 	address_space_config m_io_config;
 
+	required_shared_ptr<uint16_t> m_b0;
+	required_shared_ptr<uint16_t> m_b1;
+	required_shared_ptr<uint16_t> m_b2;
+	optional_shared_ptr<uint16_t> m_b3;
+
+	address_space *m_program;
+	direct_read_data *m_direct;
+	address_space *m_data;
+	address_space *m_io;
+
 	typedef void ( tms32025_device::*opcode_func ) ();
 	struct tms32025_opcode
 	{
@@ -156,9 +175,8 @@ private:
 	uint16_t  m_AR[8];
 	uint16_t  m_STACK[8];
 	PAIR    m_ALU;
-protected:
-	uint16_t  m_intRAM[0x800];
-private:
+	uint16_t  m_drr, m_dxr, m_tim, m_prd, m_imr, m_greg;
+
 	uint8_t   m_timerover;
 
 	/********************** Status data ****************************/
@@ -176,18 +194,6 @@ private:
 	int     m_mHackIgnoreARP;          /* special handling for lst, lst1 instructions */
 	int     m_waiting_for_serial_frame;
 
-	address_space *m_program;
-	direct_read_data *m_direct;
-	address_space *m_data;
-	address_space *m_io;
-
-	uint16_t *m_pgmmap[0x200];
-protected:
-	uint16_t *m_datamap[0x200];
-
-private:
-	uint32_t m_debugger_temp;
-
 	inline void CLR0(uint16_t flag);
 	inline void SET0(uint16_t flag);
 	inline void CLR1(uint16_t flag);
@@ -250,9 +256,9 @@ private:
 	void call();
 	void cmpl();
 	void cmpr();
-	void cnfd();
-	void cnfp();
-	void conf();
+	virtual void cnfd();
+	virtual void cnfp();
+	virtual void conf();
 	void dint();
 	void dmov();
 	void eint();
@@ -380,6 +386,9 @@ public:
 
 protected:
 	virtual void device_reset() override;
+	virtual void cnfd() override;
+	virtual void cnfp() override;
+	virtual void conf() override;
 };
 
 
diff --git a/src/devices/cpu/tms32051/tms32051.cpp b/src/devices/cpu/tms32051/tms32051.cpp
index 816af6d..5b00156 100644
--- a/src/devices/cpu/tms32051/tms32051.cpp
+++ b/src/devices/cpu/tms32051/tms32051.cpp
@@ -631,26 +631,6 @@ WRITE16_MEMBER( tms32051_device::cpuregs_w )
 }
 
 
-bool tms32051_device::memory_read(address_spacenum spacenum, offs_t offset, int size, uint64_t &value)
-{
-	/* TODO: alignment if offset is odd */
-	if (spacenum == AS_PROGRAM)
-	{
-		value = (PM_READ16(offset>>1));
-	}
-	else if (spacenum == AS_DATA)
-	{
-		value = (DM_READ16(offset>>1));
-	}
-	else if (spacenum == AS_IO)
-	{
-		value = m_io->read_word(offset);
-	}
-	return 1;
-}
-
-
-
 void tms32053_device::device_reset()
 {
 	// reset registers
diff --git a/src/devices/cpu/tms32051/tms32051.h b/src/devices/cpu/tms32051/tms32051.h
index d276ca7..de3d33e 100644
--- a/src/devices/cpu/tms32051/tms32051.h
+++ b/src/devices/cpu/tms32051/tms32051.h
@@ -77,7 +77,6 @@ protected:
 
 	// device_memory_interface overrides
 	virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const override { return (spacenum == AS_PROGRAM) ? &m_program_config : ( (spacenum == AS_IO) ? &m_io_config : ( (spacenum == AS_DATA) ? &m_data_config : nullptr ) ); }
-	virtual bool memory_read(address_spacenum spacenum, offs_t offset, int size, uint64_t &value) override;
 
 	// device_disasm_interface overrides
 	virtual uint32_t disasm_min_opcode_bytes() const override { return 2; }
diff --git a/src/devices/cpu/v810/v810.cpp b/src/devices/cpu/v810/v810.cpp
index ac5cdc7..4243aab 100644
--- a/src/devices/cpu/v810/v810.cpp
+++ b/src/devices/cpu/v810/v810.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Angelo Salese, Tomasz Slanina
 /******************************************************************
  NEC V810 (upd70732) core
diff --git a/src/devices/cpu/v810/v810.h b/src/devices/cpu/v810/v810.h
index e870f51..17e2606 100644
--- a/src/devices/cpu/v810/v810.h
+++ b/src/devices/cpu/v810/v810.h
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Angelo Salese, Tomasz Slanina
 #pragma once
 
diff --git a/src/devices/cpu/v810/v810dasm.cpp b/src/devices/cpu/v810/v810dasm.cpp
index 8b80a60..b88600d 100644
--- a/src/devices/cpu/v810/v810dasm.cpp
+++ b/src/devices/cpu/v810/v810dasm.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /********************************************
     NEC V810 (upd70732) disassembler
diff --git a/src/devices/cpu/z80/z80.cpp b/src/devices/cpu/z80/z80.cpp
index 9e0fec6..7799dff 100644
--- a/src/devices/cpu/z80/z80.cpp
+++ b/src/devices/cpu/z80/z80.cpp
@@ -3126,6 +3126,8 @@ OP(op,ff) { rst(0x38);
 
 void z80_device::take_nmi()
 {
+	PRVPC = 0xffff; // HACK: segag80r protection kludge
+
 	/* Check if processor was halted */
 	leave_halt();
 
@@ -3146,6 +3148,8 @@ void z80_device::take_interrupt()
 {
 	int irq_vector;
 
+	PRVPC = 0xffff; // HACK: segag80r protection kludge
+
 	/* Check if processor was halted */
 	leave_halt();
 
@@ -3230,6 +3234,8 @@ void z80_device::take_interrupt()
 
 void nsc800_device::take_interrupt_nsc800()
 {
+	PRVPC = 0xffff; // HACK: segag80r protection kludge
+
 	/* Check if processor was halted */
 	leave_halt();
 
diff --git a/src/devices/imagedev/floppy.cpp b/src/devices/imagedev/floppy.cpp
index fbd508c..6965258 100644
--- a/src/devices/imagedev/floppy.cpp
+++ b/src/devices/imagedev/floppy.cpp
@@ -508,6 +508,10 @@ image_init_result floppy_image_device::call_create(int format_type, util::option
 		return image_init_result::FAIL;
 	}
 
+	if (motor_always_on)
+		// When disk is inserted, start motor
+		mon_w(0);
+
 	return image_init_result::PASS;
 }
 
diff --git a/src/devices/machine/40105.cpp b/src/devices/machine/40105.cpp
index 8dec8b7..63db529 100644
--- a/src/devices/machine/40105.cpp
+++ b/src/devices/machine/40105.cpp
@@ -2,7 +2,16 @@
 // copyright-holders:Curt Coder
 /**********************************************************************
 
-    CMOS 40105 FIFO Register emulation
+    CD40105/HC40105 4-bit x 16-word FIFO Register
+
+    Part of the 4000B series of CMOS TTL devices, the 40105 includes
+    an asynchronous master reset pin intended to be connected to the
+    system bus.
+
+    Word size can be expanded from 4 bits to 8 bits by connecting two
+    40105s in parallel, with external AND gates to combine the DIR and
+    DOR outputs. They can also be connected in series to extend the
+    FIFO capacity, with DOR -> SI and /SO <- DIR.
 
 **********************************************************************/
 
@@ -22,8 +31,8 @@
 //  DEVICE DEFINITIONS
 //**************************************************************************
 
-const device_type CMOS_40105 = &device_creator<cmos_40105_device>;
-
+const device_type CD40105 = &device_creator<cmos_40105_device>;
+const device_type HC40105 = &device_creator<cmos_40105_device>;
 
 
 //**************************************************************************
@@ -34,10 +43,17 @@ const device_type CMOS_40105 = &device_creator<cmos_40105_device>;
 //  cmos_40105_device - constructor
 //-------------------------------------------------
 
-cmos_40105_device::cmos_40105_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
-	: device_t(mconfig, CMOS_40105, "40105", tag, owner, clock, "40105", __FILE__),
+cmos_40105_device::cmos_40105_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+	: device_t(mconfig, CD40105, "40105 FIFO", tag, owner, clock, "cd40105", __FILE__),
 		m_write_dir(*this),
-		m_write_dor(*this), m_d(0), m_q(0), m_dir(0), m_dor(0), m_si(0), m_so(0)
+		m_write_dor(*this),
+		m_write_q(*this),
+		m_d(0),
+		m_q(0),
+		m_dir(false),
+		m_dor(false),
+		m_si(false),
+		m_so(false)
 {
 }
 
@@ -51,6 +67,7 @@ void cmos_40105_device::device_start()
 	// resolve callbacks
 	m_write_dir.resolve_safe();
 	m_write_dor.resolve_safe();
+	m_write_q.resolve_safe();
 
 	// state saving
 	save_item(NAME(m_d));
@@ -68,36 +85,84 @@ void cmos_40105_device::device_start()
 
 void cmos_40105_device::device_reset()
 {
-	m_fifo = std::queue<uint8_t>();
-
-	m_dir = 1;
-	m_dor = 0;
-	m_si = 0;
-
-	m_write_dir(m_dir);
-	m_write_dor(m_dor);
+	// invalidate data in queue
+	m_fifo = std::queue<u8>();
+
+	// reset control flip-flops
+	m_dir = true;
+	m_dor = false;
+	m_write_dir(1);
+	m_write_dor(0);
 }
 
 
 //-------------------------------------------------
-//  read - read Q
+//  read - read output buffer (Q0 to Q3)
 //-------------------------------------------------
 
-uint8_t cmos_40105_device::read()
+u8 cmos_40105_device::read()
 {
 	return m_q;
 }
 
 
 //-------------------------------------------------
-//  write - write D
+//  write - write input buffer (D0 to D3)
 //-------------------------------------------------
 
-void cmos_40105_device::write(uint8_t data)
+void cmos_40105_device::write(u8 data)
 {
 	m_d = data & 0x0f;
 }
 
+WRITE8_MEMBER(cmos_40105_device::write)
+{
+	write(data);
+}
+
+
+//-------------------------------------------------
+//  load_input - load new data into FIFO
+//-------------------------------------------------
+
+void cmos_40105_device::load_input()
+{
+	if (m_fifo.size() == 16)
+	{
+		logerror("Attempt to load data into full FIFO\n");
+		return;
+	}
+
+	m_fifo.push(m_d);
+
+	// DIR remains low if FIFO is full, or else briefly pulses low
+	m_write_dir(0);
+	if (m_fifo.size() == 16)
+		m_dir = false;
+	else
+		m_write_dir(1);
+}
+
+
+//-------------------------------------------------
+//  output_ready - place new data at output
+//-------------------------------------------------
+
+void cmos_40105_device::output_ready()
+{
+	if (m_fifo.size() == 0)
+	{
+		logerror("Attempt to output data from empty FIFO\n");
+		return;
+	}
+
+	m_q = m_fifo.front();
+	m_write_q(m_q);
+
+	m_dor = true;
+	m_write_dor(1);
+}
+
 
 //-------------------------------------------------
 //  si_w - shift in write
@@ -105,22 +170,16 @@ void cmos_40105_device::write(uint8_t data)
 
 WRITE_LINE_MEMBER( cmos_40105_device::si_w )
 {
+	// load input on rising edge when ready
 	if (m_dir && !m_si && state)
 	{
-		m_fifo.push(m_d);
-
-		if (m_fifo.size() == 16)
-		{
-			m_dir = 0;
-			m_write_dir(m_dir);
-		}
-
+		load_input();
+	}
+	else if (m_si && !state && m_fifo.size() > 0)
+	{
+		// data propagates through FIFO when SI goes low
 		if (!m_dor)
-		{
-			m_dor = 1;
-			m_write_dor(m_dor);
-		}
-
+			output_ready();
 	}
 
 	m_si = state;
@@ -133,18 +192,26 @@ WRITE_LINE_MEMBER( cmos_40105_device::si_w )
 
 WRITE_LINE_MEMBER( cmos_40105_device::so_w )
 {
-	if (m_dor && m_so && !m_so)
+	// shift out on falling edge when ready
+	if (m_dor && m_so && !state)
 	{
-		m_dor = 0;
-		m_write_dor(m_dor);
-
-		m_q = m_fifo.front();
 		m_fifo.pop();
+		m_dor = false;
+		m_write_dor(0);
 
+		// DOR remains low if FIFO is now empty, or else briefly pulses low
 		if (m_fifo.size() > 0)
+			output_ready();
+
+		if (!m_dir)
 		{
-			m_dor = 1;
-			m_write_dor(m_dor);
+			// raise DIR since FIFO is no longer full
+			m_dir = true;
+			m_write_dir(1);
+
+			// load new input immediately if SI is held high
+			if (m_si)
+				load_input();
 		}
 	}
 
diff --git a/src/devices/machine/40105.h b/src/devices/machine/40105.h
index 67d3a58..47a8ce0 100644
--- a/src/devices/machine/40105.h
+++ b/src/devices/machine/40105.h
@@ -2,7 +2,18 @@
 // copyright-holders:Curt Coder
 /**********************************************************************
 
-    CMOS 40105 FIFO Register emulation
+    CD40105/HC40105 4-bit x 16-word FIFO Register
+
+***********************************************************************
+                                ____   ____
+                       /OE   1 |*   \_/    | 16  Vcc
+                       DIR   2 |           | 15  /SO
+                        SI   3 |           | 14  DOR
+                        D0   4 |           | 13  Q0
+                        D1   5 |   40105   | 12  Q1
+                        D2   6 |           | 11  Q2
+                        D3   7 |           | 10  Q3
+                       GND   8 |___________|  9  MR
 
 **********************************************************************/
 
@@ -20,11 +31,15 @@
 //  INTERFACE CONFIGURATION MACROS
 ///*************************************************************************
 
-#define MCFG_40105_ADD(_tag, _dir, _dor) \
-	MCFG_DEVICE_ADD(_tag, CMOS_40105, 0) \
-	downcast<cmos_40105_device *>(device)->set_dir_callback(DEVCB_##_dir); \
+#define MCFG_40105_DATA_IN_READY_CB(_dir) \
+	downcast<cmos_40105_device *>(device)->set_dir_callback(DEVCB_##_dir);
+
+#define MCFG_40105_DATA_OUT_READY_CB(_dor) \
 	downcast<cmos_40105_device *>(device)->set_dor_callback(DEVCB_##_dor);
 
+#define MCFG_40105_DATA_OUT_CB(_out) \
+	downcast<cmos_40105_device *>(device)->set_data_out_callback(DEVCB_##_out);
+
 
 
 ///*************************************************************************
@@ -37,13 +52,15 @@ class cmos_40105_device :  public device_t
 {
 public:
 	// construction/destruction
-	cmos_40105_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+	cmos_40105_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
 
 	template<class _dir> void set_dir_callback(_dir dir) { m_write_dir.set_callback(dir); }
 	template<class _dor> void set_dor_callback(_dor dor) { m_write_dor.set_callback(dor); }
+	template<class _out> void set_data_out_callback(_out out) { m_write_q.set_callback(out); }
 
-	uint8_t read();
-	void write(uint8_t data);
+	u8 read();
+	void write(u8 data);
+	DECLARE_WRITE8_MEMBER(write);
 
 	DECLARE_WRITE_LINE_MEMBER( si_w );
 	DECLARE_WRITE_LINE_MEMBER( so_w );
@@ -57,24 +74,30 @@ protected:
 	virtual void device_reset() override;
 
 private:
+	// private helpers
+	void load_input();
+	void output_ready();
+
+	// callbacks
 	devcb_write_line m_write_dir;
 	devcb_write_line m_write_dor;
+	devcb_write8 m_write_q;
 
-	std::queue<uint8_t> m_fifo;
+	std::queue<u8> m_fifo;
 
-	uint8_t m_d;
-	uint8_t m_q;
+	u8 m_d;
+	u8 m_q;
 
-	int m_dir;
-	int m_dor;
-	int m_si;
-	int m_so;
+	bool m_dir;
+	bool m_dor;
+	bool m_si;
+	bool m_so;
 };
 
 
 // device type definition
-extern const device_type CMOS_40105;
-
+extern const device_type CD40105;
+extern const device_type HC40105;
 
 
 #endif
diff --git a/src/devices/machine/68230pit.cpp b/src/devices/machine/68230pit.cpp
index 9e66dcb..ab6cbd0 100644
--- a/src/devices/machine/68230pit.cpp
+++ b/src/devices/machine/68230pit.cpp
@@ -4,23 +4,21 @@
 *
 *   Motorola MC68230 PI/T Parallel Interface and Timer
 *
-* PORT MODES INCLUDE :
-* - BIT I/O
-* - UNIDIRECTIONAL 8 BIT AND 16 BIT
-* - BIDIRECTIONAL 8 BIT AND 16 BIT
-* PROGRAMMABLE HANDSHAKING OPTIONS
-* 24-BIT PROGRAMMABLE TIMER MODES
-* FIVE SEPARATE INTERRUPT VECTORS SEPARATE PORT AND TIMER INTERRUPT SERVICE REQUESTS
-* REGISTERS AREREAD/WRITEAND DIRECTLY ADDRESSABLE
-* REGISTERS ARE ADDRESSED FOR MOVEP (Move Peripheral) AND DMAC COMPATIBILITY
-*
-*  Revisions: 2015-07-15 JLE initial
+* Port modes include :
+* - bit i/o
+* - unidirectional 8 bit and 16 bit
+* - bidirectional 8 bit and 16 bit
+* Programmable handshaking options
+* 24-bit programmable timer modes
+* Five separate interrupt vectors separate port and timer interrupt service requests
+* Registers are read/write and directly addressable
+* Registers are addressed for movep (move peripheral) and dmac compatibility
 *
 *  Todo
 *  - Complete support for clock and timers
-*  - Add interrupt support
+*  - Complete interrupt support
 *  - Add DMA support
-*  - Add double buffering for each submode
+*  - Add appropriate buffering for each submode
 **********************************************************************/
 
 #include "68230pit.h"
@@ -30,6 +28,8 @@
 #define LOGPRINT(x) { do { if (VERBOSE) logerror x; } while (0); }
 #define LOG(x)      {} LOGPRINT(x)
 #define LOGR(x)     {} LOGPRINT(x)
+#define LOGBIT(x)   {} LOGPRINT(x)
+#define LOGDR(x)    {} LOGPRINT(x)
 #define LOGINT(x)   {} LOGPRINT(x)
 #define LOGSETUP(x) {} LOGPRINT(x)
 #if VERBOSE > 1
@@ -65,6 +65,8 @@ pit68230_device::pit68230_device(const machine_config &mconfig, device_type type
 	, m_h2_out_cb (*this)
 	, m_h3_out_cb (*this)
 	, m_h4_out_cb (*this)
+	, m_tirq_out_cb (*this)
+	, m_pirq_out_cb (*this)
 	, m_pgcr(0)
 	, m_psrr(0)
 	, m_paddr(0)
@@ -101,6 +103,8 @@ pit68230_device::pit68230_device(const machine_config &mconfig, const char *tag,
 	, m_h2_out_cb(*this)
 	, m_h3_out_cb(*this)
 	, m_h4_out_cb(*this)
+	, m_tirq_out_cb (*this)
+	, m_pirq_out_cb (*this)
 	, m_pgcr(0)
 	, m_psrr(0)
 	, m_paddr(0)
@@ -137,11 +141,13 @@ void pit68230_device::device_start ()
 	m_pb_out_cb.resolve_safe();
 	m_pb_in_cb.resolve_safe(0);
 	m_pc_out_cb.resolve_safe();
-	m_pc_in_cb.resolve_safe(0);
+	m_pc_in_cb.resolve(); // A temporary way to check if handler is installed with isnull(). TODO: Need better fix.
 	m_h1_out_cb.resolve_safe();
 	m_h2_out_cb.resolve_safe();
 	m_h3_out_cb.resolve_safe();
 	m_h4_out_cb.resolve_safe();
+	m_tirq_out_cb.resolve_safe();
+	m_pirq_out_cb.resolve_safe();
 
 	// Timers
 	pit_timer = timer_alloc(TIMER_ID_PIT);
@@ -178,52 +184,159 @@ void pit68230_device::device_reset ()
 	m_paddr = 0;
 	m_pbddr = 0;
 	m_pcddr = 0;
-	m_pivr = 0x0f;
-	m_pacr = 0; m_h2_out_cb(m_pacr);
-	m_pbcr = 0;
+	m_pivr = 0x0f;  m_pirq_out_cb(CLEAR_LINE);
+	m_pacr = 0; m_h2_out_cb(CLEAR_LINE);
+	m_pbcr = 0; m_h4_out_cb(CLEAR_LINE);
 	m_padr = 0; m_pa_out_cb((offs_t)0, m_padr);
 	m_pbdr = 0; m_pb_out_cb((offs_t)0, m_pbdr);
+	m_pcdr = 0; m_pc_out_cb((offs_t)0, m_pcdr);
 	m_psr = 0;
 	m_tcr = 0;
-	m_tivr = 0x0f;
+	m_tivr = 0x0f; m_tirq_out_cb(CLEAR_LINE);
 	m_tsr = 0;
 }
 
-//-------------------------------------------------
-//  device_timer - handler timer events
-//-------------------------------------------------
-void pit68230_device::device_timer (emu_timer &timer, device_timer_id id, int32_t param, void *ptr)
+/*
+ * PIACK* provides the Port vector in an iack cycle modified by source H1-H4
+ */
+uint8_t pit68230_device::irq_piack()
 {
-	switch(id)
+	LOGINT(("%s %s <- %02x\n",tag(), FUNCNAME, m_pivr));
+	return m_pivr;
+}
+
+/*
+ * TIACK* provides the Timer vector in an iack cycle
+ */
+uint8_t pit68230_device::irq_tiack()
+{
+	LOGINT(("%s %s <- %02x\n",tag(), FUNCNAME, m_tivr));
+	return m_tivr;
+}
+
+/*
+ * trigger_interrupt - called when a potential interrupt condition occurs
+ * but will only generate an interrupt when the PIT is programmed to do so.
+ */
+void pit68230_device::trigger_interrupt(int source)
+{
+	LOGINT(("%s %s Source: %02x\n",tag(), FUNCNAME, source));
+
+	if (source == INT_TIMER)
+	{
+		// TODO: implement priorities and support nested interrupts
+		if ( (m_tcr & REG_TCR_TOUT_TIACK_MASK) == REG_TCR_TOUT_TIACK_INT ||
+			 (m_tcr & REG_TCR_TOUT_TIACK_MASK) == REG_TCR_TOUT_PC7_INT )
+			{
+				m_tirq_out_cb(ASSERT_LINE);
+			}
+	}
+	else
+	{
+		// TODO: implement priorities and support nested interrupts for the H1-H4 sources
+		m_pirq_out_cb(ASSERT_LINE);
+	}
+}
+
+void pit68230_device::tick_clock()
+{
+	if (m_tcr & REG_TCR_TIMER_ENABLE)
 	{
-	case TIMER_ID_PIT:
 		if (m_cntr-- == 0) // Zero detect
 		{
-			/* TODO: Check mode and use preload value if required or just rollover 24 bit */
+			LOGINT(("Timer reached zero!\n"));
 			if ((m_tcr & REG_TCR_ZD) == 0)
 				m_cntr = m_cpr;
 			else // mask off to 24 bit on rollover
 				m_cntr &= 0xffffff;
+			m_tsr = 1;
+			trigger_interrupt(INT_TIMER);
 		}
+	}
+}
+
+//-------------------------------------------------
+//  device_timer - handler timer events
+//-------------------------------------------------
+void pit68230_device::device_timer (emu_timer &timer, device_timer_id id, int32_t param, void *ptr)
+{
+	switch(id)
+	{
+	case TIMER_ID_PIT:
+		tick_clock();
 		break;
 	default:
-		LOGINT(("Unhandled Timer ID %d\n", id));
+		LOG(("Unhandled Timer ID %d\n", id));
 		break;
 	}
 }
 
 void pit68230_device::h1_set (uint8_t state)
 {
-	LOG(("%s %s %d @ m_psr %2x => ",tag(), FUNCNAME, state, m_psr));
 	if (state) m_psr |= 1; else m_psr &= ~1;
-	LOG(("%02x %lld\n", m_psr, machine ().firstcpu->total_cycles ()));
 }
 
-void pit68230_device::portb_setbit (uint8_t bit, uint8_t state)
+// TODO: remove this method and replace it with a call to pb_update_bit() in force68k.cpp
+void pit68230_device::portb_setbit(uint8_t bit, uint8_t state)
 {
-	LOG(("%s %s %d/%d @ m_pbdr %2x => ", tag(), FUNCNAME, bit, state, m_pbdr));
 	if (state) m_pbdr |= (1 << bit); else m_pbdr &= ~(1 << bit);
-	LOG(("%02x %lld\n", m_pbdr, machine ().firstcpu->total_cycles ()));
+}
+
+void pit68230_device::pa_update_bit(uint8_t bit, uint8_t state)
+{
+	LOGBIT(("%s %s bit %d to %d\n",tag(), FUNCNAME, bit, state));
+	// Check if requested bit is an output bit and can't be affected
+	if (m_paddr & (1 << bit))
+	{
+		LOG(("- 68230 PIT: tried to set input bit at port A that is programmed as output!\n"));
+		return;
+	}
+	if (state)
+		m_padr |= (1 << bit);
+	else
+		m_padr &= ~(1 << bit);
+}
+
+void pit68230_device::pb_update_bit(uint8_t bit, uint8_t state)
+{
+	LOGBIT(("%s %s bit %d to %d\n",tag(), FUNCNAME, bit, state));
+	// Check if requested bit is an output bit and can't be affected
+	if (m_pbddr & (1 << bit))
+	{
+		LOG(("- 68230 PIT: tried to set input bit at port B that is programmed as output!\n"));
+		return;
+	}
+	if (state)
+		m_pbdr |= (1 << bit);
+	else
+		m_pbdr &= ~(1 << bit);
+}
+
+// TODO: Make sure port C is in the right alternate mode
+void pit68230_device::pc_update_bit(uint8_t bit, uint8_t state)
+{
+	LOGBIT(("%s %s bit %d to %d\n",tag(), FUNCNAME, bit, state));
+	// Check if requested bit is an output bit and can't be affected
+	if (m_pcddr & (1 << bit))
+	{
+		LOG(("- 68230 PIT: tried to set input bit at port C that is programmed as output!\n"));
+		return;
+	}
+	if (state)
+		m_pcdr |= (1 << bit);
+	else
+		m_pcdr &= ~(1 << bit);
+}
+
+void pit68230_device::update_tin(uint8_t state)
+{
+	// Tick clock on falling edge. TODO: check what flank is correct
+	if (state == CLEAR_LINE)
+	{
+		tick_clock();
+	}
+
+	pc_update_bit(REG_PCDR_TIN_BIT, state == ASSERT_LINE ? 0 : 1);
 }
 
 #if VERBOSE > 2
@@ -298,36 +411,97 @@ void pit68230_device::wr_pitreg_pacr(uint8_t data)
 	 * 1 X0  Output pin - negated, H2S is always cleared.
 	 * 1 X1  Output pin - asserted, H2S is always cleared.
 	 */
-	m_h2_out_cb (m_pacr & 0x08 ? 1 : 0); // TODO: Check mode and submodes
+	if (m_pgcr & REG_PGCR_H12_ENABLE)
+	{
+		if (m_pacr & REG_PACR_H2_CTRL_IN_OUT)
+		{
+			switch(m_pacr & REG_PACR_H2_CTRL_MASK)
+			{
+			case REG_PACR_H2_CTRL_OUT_00:
+				LOG((" - H2 cleared\n"));
+				m_h2_out_cb(CLEAR_LINE);
+				break;
+			case REG_PACR_H2_CTRL_OUT_01:
+				LOG((" - H2 asserted\n"));
+				m_h2_out_cb(ASSERT_LINE);
+				break;
+			case REG_PACR_H2_CTRL_OUT_10:
+				LOGSETUP((" - interlocked handshake not implemented\n"));
+				break;
+			case REG_PACR_H2_CTRL_OUT_11:
+				LOGSETUP((" - pulsed handshake not implemented\n"));
+				break;
+			default: logerror(("Undefined H2 mode, broken driver - please report!\n"));
+			}
+		}
+	}
+	else
+	{
+		LOG((" - H2 cleared because being disabled in PGCR\n"));
+		m_h2_out_cb(CLEAR_LINE);
+	}
 }
 
+// TODO add support for sense status
 void pit68230_device::wr_pitreg_pbcr(uint8_t data)
 {
 	LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, tag(), FUNCNAME, data));
 	m_pbcr = data;
+	if ((m_pgcr & REG_PGCR_H34_ENABLE) || ((m_pbcr & REG_PBCR_SUBMODE_MASK) == REG_PBCR_SUBMODE_1X))
+	{
+		if (m_pbcr & REG_PBCR_H4_CTRL_IN_OUT)
+		{
+			switch(m_pbcr & REG_PBCR_H4_CTRL_MASK)
+			{
+			case REG_PBCR_H4_CTRL_OUT_00:
+				LOG((" - H4 cleared\n"));
+				m_h4_out_cb(CLEAR_LINE);
+				break;
+			case REG_PBCR_H4_CTRL_OUT_01:
+				LOG((" - H4 asserted\n"));
+				m_h4_out_cb(ASSERT_LINE);
+				break;
+			case REG_PBCR_H4_CTRL_OUT_10:
+				LOGSETUP((" - interlocked handshake not implemented\n"));
+				break;
+			case REG_PBCR_H4_CTRL_OUT_11:
+				LOGSETUP((" - pulsed handshake not implemented\n"));
+				break;
+			default: logerror(("Undefined H4 mode, broken driver - please report!\n"));
+			}
+		}
+	}
+	else
+	{
+		LOG((" - H4 cleared because being disabled in PGCR\n"));
+		m_h4_out_cb(CLEAR_LINE);
+	}
 }
 
 void pit68230_device::wr_pitreg_padr(uint8_t data)
 {
 	LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, tag(), FUNCNAME, data));
-	m_padr |= (data & m_paddr);
-	// callbacks
+	m_padr = (data & m_paddr);
+
+	// callback
 	m_pa_out_cb ((offs_t)0, m_padr);
 }
 
 void pit68230_device::wr_pitreg_pbdr(uint8_t data)
 {
 	LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, tag(), FUNCNAME, data));
-	m_pbdr |= (data & m_pbddr);
-	// callbacks
+	m_pbdr = (data & m_pbddr);
+
+	// callback
 	m_pb_out_cb ((offs_t)0, m_pbdr & m_pbddr);
 }
 
 void pit68230_device::wr_pitreg_pcdr(uint8_t data)
 {
 	LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, tag(), FUNCNAME, data));
-	m_pcdr |= (data & m_pcddr);
-	// callbacks
+	m_pcdr = (data & m_pcddr);
+
+	// callback
 	m_pc_out_cb ((offs_t)0, m_pcdr);
 }
 
@@ -416,19 +590,19 @@ void pit68230_device::wr_pitreg_tcr(uint8_t data)
 	case REG_TCR_PC3_PC7:
 	case REG_TCR_PC3_PC7_DC:        LOG(("- PC3 and PC7 used as I/O pins\n")); break;
 	case REG_TCR_TOUT_PC7_SQ:
-	case REG_TCR_TOUT_PC7_SQ_DC:    LOG(("- PC3 used as SQuare wave TOUT and PC7 used as I/O pin - not supported yet\n")); sqr = 1; break;
-	case REG_TCR_TOUT_TIACK:        LOG(("- PC3 used as TOUT and PC7 used as TIACK - not supported yet\n")); tout = 1; tiack = 1; break;
-	case REG_TCR_TOUT_TIACK_INT:    LOG(("- PC3 used as TOUT and PC7 used as TIACK, Interrupts enabled - not supported yet\n")); tout = 1; tiack = 1; irq = 1; break;
-	case REG_TCR_TOUT_PC7:          LOG(("- PC3 used as TOUT and PC7 used as I/O pin - not supported yet\n")); break;
-	case REG_TCR_TOUT_PC7_INT:      LOG(("- PC3 used as TOUT and PC7 used as I/O pin, Interrupts enabled - not supported yet\n")); break;
+	case REG_TCR_TOUT_PC7_SQ_DC:    LOG(("- PC3 used as SQuare wave TOUT and PC7 used as I/O pin - not implemented yet\n"));        sqr = 1; break;
+	case REG_TCR_TOUT_TIACK:        LOG(("- PC3 used as TOUT and PC7 used as TIACK - not implemented yet\n")); tout = 1; tiack = 1;          break;
+	case REG_TCR_TOUT_TIACK_INT:    LOG(("- PC3 used as TOUT and PC7 used as TIACK, Interrupts enabled\n"));   tout = 1; tiack = 1; irq = 1; break;
+	case REG_TCR_TOUT_PC7:          LOG(("- PC3 used as TOUT and PC7 used as I/O pin - not implemented yet\n"));                             break;
+	case REG_TCR_TOUT_PC7_INT:      LOG(("- PC3 used as TOUT and PC7 used as I/O pin, Interrupts enabled\n")); tout = 1; irq = 1;            break;
 	}
 
 	switch (m_tcr & REG_TCR_CC_MASK)
 	{
-	case REG_TCR_CC_PC2_CLK_PSC:    LOG(("- PC2 used as I/O pin,CLK and x32 prescaler are used\n")); clk = 1; psc = 1; break;
-	case REG_TCR_CC_TEN_CLK_PSC:    LOG(("- PC2 used as Timer enable/disable, CLK and presacaler are used\n")); pen = 1; clk = 1; psc = 1; break;
-	case REG_TCR_CC_TIN_PSC:        LOG(("- PC2 used as Timer clock and the presacaler is used - not supported yet\n")); psc = 1; break;
-	case REG_TCR_CC_TIN_RAW:        LOG(("- PC2 used as Timer clock and the presacaler is NOT used - not supported yet\n")); break;
+	case REG_TCR_CC_PC2_CLK_PSC:    LOG(("- PC2 used as I/O pin,CLK and x32 prescaler are used\n"));                                       clk = 1; psc = 1; break;
+	case REG_TCR_CC_TEN_CLK_PSC:    LOG(("- PC2 used as Timer enable/disable, CLK and presacaler are used - not implemented\n")); pen = 1; clk = 1; psc = 1; break;
+	case REG_TCR_CC_TIN_PSC:        LOG(("- PC2 used as Timer clock and the presacaler is used - not implemented\n"));                              psc = 1; break;
+	case REG_TCR_CC_TIN_RAW:        LOG(("- PC2 used as Timer clock and the presacaler is NOT used\n")); break;
 	}
 	LOG(("%s", m_tcr & REG_TCR_ZR ? "- Spec violation, should always be 0!\n" : ""));
 	LOG(("- Timer %s when reaching 0 (zero)\n", m_tcr & REG_TCR_ZD ? "rolls over" : "reload the preload values"));
@@ -437,7 +611,10 @@ void pit68230_device::wr_pitreg_tcr(uint8_t data)
 	if (m_tcr & REG_TCR_ENABLE)
 	{
 		m_cntr = 0;
-		if (pen == 1){ LOG(("PC2 enable/disable TBD\n")); }
+		if (pen == 1)
+		{
+			LOG(("PC2 enable/disable TBD\n"));
+		}
 		if (clk == 1)
 		{
 			int rate = clock() / (psc == 1 ? 32 : 1);
@@ -482,7 +659,11 @@ void pit68230_device::wr_pitreg_cprl(uint8_t data)
 void pit68230_device::wr_pitreg_tsr(uint8_t data)
 {
 	LOG(("%s(%02x) \"%s\": \n", FUNCNAME, data, tag()));
-	m_tsr = data;
+	if (data & 1)
+	{
+		m_tsr = 0; // A write resets the TSR;
+		m_tirq_out_cb(CLEAR_LINE);
+	}
 }
 
 WRITE8_MEMBER (pit68230_device::write)
@@ -592,7 +773,7 @@ uint8_t pit68230_device::rr_pitreg_padr()
 {
 	m_padr &= m_paddr;
 	m_padr |= (m_pa_in_cb() & ~m_paddr);
-	LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, m_padr));
+	LOGDR(("%s %s <- %02x\n",tag(), FUNCNAME, m_padr));
 	return m_padr;
 }
 
@@ -607,15 +788,19 @@ uint8_t pit68230_device::rr_pitreg_pbdr()
 {
 	m_pbdr &= m_pbddr;
 	m_pbdr |= (m_pb_in_cb() & ~m_pbddr);
-	LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, m_pbdr));
+
+	LOGDR(("%s %s <- %02x\n",tag(), FUNCNAME, m_pbdr));
 	return m_pbdr;
 }
 
 uint8_t pit68230_device::rr_pitreg_pcdr()
 {
-	m_pcdr &= m_pcddr;
-	m_pcdr |= (m_pc_in_cb() & ~m_pcddr);
-	LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, m_pcdr));
+	if (!m_pc_in_cb.isnull()) // Port C has alternate functions that may set bits apart from callback
+	{
+		m_pcdr &= m_pcddr;
+		m_pcdr |= (m_pc_in_cb() & ~m_pcddr);
+	}
+	if (m_pcdr != 0) { LOGDR(("%s %s <- %02x\n",tag(), FUNCNAME, m_pcdr)); }
 	return m_pcdr;
 }
 
@@ -739,7 +924,7 @@ READ8_MEMBER (pit68230_device::read){
 	case PIT_68230_CNTRL:   data = rr_pitreg_cntrl(); break;
 	case PIT_68230_TSR:     data = rr_pitreg_tsr(); break;
 	default:
-		LOG (("Unhandled read register %02x\n", offset));
+		LOG (("Unhandled read register %02x returning 0x00\n", offset));
 		data = 0;
 	}
 
diff --git a/src/devices/machine/68230pit.h b/src/devices/machine/68230pit.h
index 0fe41d1..30850ab 100644
--- a/src/devices/machine/68230pit.h
+++ b/src/devices/machine/68230pit.h
@@ -44,34 +44,40 @@
 //**************************************************************************
 
 #define MCFG_PIT68230_PA_INPUT_CB(_devcb) \
-		devcb = &pit68230_device::set_pa_in_callback (*device, DEVCB_##_devcb);
+	devcb = &pit68230_device::set_pa_in_callback (*device, DEVCB_##_devcb);
 
 #define MCFG_PIT68230_PA_OUTPUT_CB(_devcb) \
-		devcb = &pit68230_device::set_pa_out_callback (*device, DEVCB_##_devcb);
+	devcb = &pit68230_device::set_pa_out_callback (*device, DEVCB_##_devcb);
 
 #define MCFG_PIT68230_PB_INPUT_CB(_devcb) \
-		devcb = &pit68230_device::set_pb_in_callback (*device, DEVCB_##_devcb);
+	devcb = &pit68230_device::set_pb_in_callback (*device, DEVCB_##_devcb);
 
 #define MCFG_PIT68230_PB_OUTPUT_CB(_devcb) \
-		devcb = &pit68230_device::set_pb_out_callback (*device, DEVCB_##_devcb);
+	devcb = &pit68230_device::set_pb_out_callback (*device, DEVCB_##_devcb);
 
 #define MCFG_PIT68230_PC_INPUT_CB(_devcb) \
-		devcb = &pit68230_device::set_pc_in_callback (*device, DEVCB_##_devcb);
+	devcb = &pit68230_device::set_pc_in_callback (*device, DEVCB_##_devcb);
 
 #define MCFG_PIT68230_PC_OUTPUT_CB(_devcb) \
-		devcb = &pit68230_device::set_pc_out_callback (*device, DEVCB_##_devcb);
+	devcb = &pit68230_device::set_pc_out_callback (*device, DEVCB_##_devcb);
 
 #define MCFG_PIT68230_H1_CB(_devcb) \
-		devcb = &pit68230_device::set_h1_out_callback (*device, DEVCB_##_devcb);
+	devcb = &pit68230_device::set_h1_out_callback (*device, DEVCB_##_devcb);
 
 #define MCFG_PIT68230_H2_CB(_devcb) \
-		devcb = &pit68230_device::set_h2_out_callback (*device, DEVCB_##_devcb);
+	devcb = &pit68230_device::set_h2_out_callback (*device, DEVCB_##_devcb);
 
 #define MCFG_PIT68230_H3_CB(_devcb) \
-		devcb = &pit68230_device::set_h3_out_callback (*device, DEVCB_##_devcb);
+	devcb = &pit68230_device::set_h3_out_callback (*device, DEVCB_##_devcb);
 
 #define MCFG_PIT68230_H4_CB(_devcb) \
-		devcb = &pit68230_device::set_h4_out_callback (*device, DEVCB_##_devcb);
+	devcb = &pit68230_device::set_h4_out_callback (*device, DEVCB_##_devcb);
+
+#define MCFG_PIT68230_TIMER_IRQ_CB(_devcb) \
+	devcb = &pit68230_device::set_tirq_out_callback(*device, DEVCB_##_devcb);
+
+#define MCFG_PIT68230_PORT_IRQ_CB(_devcb) \
+	devcb = &pit68230_device::set_pirq_out_callback(*device, DEVCB_##_devcb);
 
 /*-----------------------------------------------------------------------
  * Registers                RS1-RS5   R/W Description
@@ -119,6 +125,8 @@ class pit68230_device :  public device_t//, public device_execute_interface
 	template<class _Object> static devcb_base &set_h2_out_callback (device_t &device, _Object object){ return downcast<pit68230_device &>(device).m_h2_out_cb.set_callback (object); }
 	template<class _Object> static devcb_base &set_h3_out_callback (device_t &device, _Object object){ return downcast<pit68230_device &>(device).m_h3_out_cb.set_callback (object); }
 	template<class _Object> static devcb_base &set_h4_out_callback (device_t &device, _Object object){ return downcast<pit68230_device &>(device).m_h4_out_cb.set_callback (object); }
+	template<class _Object> static devcb_base &set_tirq_out_callback (device_t &device, _Object object){ return downcast<pit68230_device &>(device).m_tirq_out_cb.set_callback (object); }
+	template<class _Object> static devcb_base &set_pirq_out_callback (device_t &device, _Object object){ return downcast<pit68230_device &>(device).m_pirq_out_cb.set_callback (object); }
 
 	DECLARE_WRITE8_MEMBER (write);
 	DECLARE_READ8_MEMBER (read);
@@ -126,6 +134,40 @@ class pit68230_device :  public device_t//, public device_execute_interface
 	void h1_set (uint8_t state);
 	void portb_setbit (uint8_t bit, uint8_t state);
 
+	// Bit updaters
+	void pa_update_bit(uint8_t bit, uint8_t state);
+	void pb_update_bit(uint8_t bit, uint8_t state);
+	void pc_update_bit(uint8_t bit, uint8_t state);
+	void update_tin(uint8_t);
+
+	DECLARE_WRITE_LINE_MEMBER( pa0_w ){ pa_update_bit(0, state); }
+	DECLARE_WRITE_LINE_MEMBER( pa1_w ){ pa_update_bit(1, state); }
+	DECLARE_WRITE_LINE_MEMBER( pa2_w ){ pa_update_bit(2, state); }
+	DECLARE_WRITE_LINE_MEMBER( pa3_w ){ pa_update_bit(3, state); }
+	DECLARE_WRITE_LINE_MEMBER( pa4_w ){ pa_update_bit(4, state); }
+	DECLARE_WRITE_LINE_MEMBER( pa5_w ){ pa_update_bit(5, state); }
+	DECLARE_WRITE_LINE_MEMBER( pa6_w ){ pa_update_bit(6, state); }
+	DECLARE_WRITE_LINE_MEMBER( pa7_w ){ pa_update_bit(7, state); }
+
+	DECLARE_WRITE_LINE_MEMBER( pb0_w ){ pb_update_bit(0, state); }
+	DECLARE_WRITE_LINE_MEMBER( pb1_w ){ pb_update_bit(1, state); }
+	DECLARE_WRITE_LINE_MEMBER( pb2_w ){ pb_update_bit(2, state); }
+	DECLARE_WRITE_LINE_MEMBER( pb3_w ){ pb_update_bit(3, state); }
+	DECLARE_WRITE_LINE_MEMBER( pb4_w ){ pb_update_bit(4, state); }
+	DECLARE_WRITE_LINE_MEMBER( pb5_w ){ pb_update_bit(5, state); }
+	DECLARE_WRITE_LINE_MEMBER( pb6_w ){ pb_update_bit(6, state); }
+	DECLARE_WRITE_LINE_MEMBER( pb7_w ){ pb_update_bit(7, state); }
+
+	DECLARE_WRITE_LINE_MEMBER( pc0_w ){ pc_update_bit(0, state); }
+	DECLARE_WRITE_LINE_MEMBER( pc1_w ){ pc_update_bit(1, state); }
+	DECLARE_WRITE_LINE_MEMBER( pc2_w ){ pc_update_bit(2, state); }
+	DECLARE_WRITE_LINE_MEMBER( pc3_w ){ pc_update_bit(3, state); }
+	DECLARE_WRITE_LINE_MEMBER( pc4_w ){ pc_update_bit(4, state); }
+	DECLARE_WRITE_LINE_MEMBER( pc5_w ){ pc_update_bit(5, state); }
+	DECLARE_WRITE_LINE_MEMBER( pc6_w ){ pc_update_bit(6, state); }
+	DECLARE_WRITE_LINE_MEMBER( pc7_w ){ pc_update_bit(7, state); }
+
+ private:
 	void wr_pitreg_pgcr(uint8_t data);
 	void wr_pitreg_psrr(uint8_t data);
 	void wr_pitreg_paddr(uint8_t data);
@@ -173,7 +215,65 @@ class pit68230_device :  public device_t//, public device_execute_interface
 
 protected:
 
+	enum { // PGCR - Port Global Control register
+		REG_PGCR_MODE_MASK      = 0xc0,
+		REG_PGCR_MODE_0         = 0x00, // 0 0 Unidirectional  8 bit mode
+		REG_PGCR_MODE_1         = 0x40, // 0 1 Unidirectional 16 bit mode
+		REG_PGCR_MODE_2         = 0x80, // 1 0 Bidirectional   8 bit mode
+		REG_PGCR_MODE_3         = 0xc0, // 1 1 Bidirectional  16 bit mode
+		REG_PGCR_H34_ENABLE     = 0x20,
+		REG_PGCR_H12_ENABLE     = 0x10,
+		REG_PGCR_H4_SENSE       = 0x80,
+		REG_PGCR_H3_SENSE       = 0x40,
+		REG_PGCR_H2_SENSE       = 0x20,
+		REG_PGCR_H1_SENSE       = 0x10,
+	};
+
+	enum {
+		REG_PACR_SUBMODE_MASK   = 0xc0,
+		REG_PACR_SUBMODE_0      = 0x00, // 0 0
+		REG_PACR_SUBMODE_1      = 0x40, // 0 1
+		REG_PACR_SUBMODE_2      = 0x80, // 1 0
+		REG_PACR_SUBMODE_3      = 0xc0, // 1 1
+		REG_PACR_H2_CTRL_MASK   = 0x38,
+		REG_PACR_H2_CTRL_IN_OUT = 0x20, // H2 sense always cleared if set
+		REG_PACR_H2_CTRL_OUT_00 = 0x20, // H2 output negated
+		REG_PACR_H2_CTRL_OUT_01 = 0x28, // H2 output asserted
+		REG_PACR_H2_CTRL_OUT_10 = 0x30, // H2 output in interlocked input handshake protocol
+		REG_PACR_H2_CTRL_OUT_11 = 0x38, // H2 output in pulsed input handshake protocol
+		REG_PACR_H2_INT_ENABLE  = 0x04,
+		REG_PACR_H1_SVCR_ENABLE = 0x02,
+		REG_PACR_H1_STATUS_CTRL = 0x01,
+	};
+
+	enum {
+		REG_PBCR_SUBMODE_MASK   = 0xc0,
+		REG_PBCR_SUBMODE_00     = 0x00, // 0 0
+		REG_PBCR_SUBMODE_01     = 0x40, // 0 1
+		REG_PBCR_SUBMODE_10     = 0x80, // 1 0
+		REG_PBCR_SUBMODE_11     = 0xc0, // 1 1
+		REG_PBCR_SUBMODE_1X     = 0x80, // submode 2 or 3
+		REG_PBCR_H4_CTRL_MASK   = 0x38,
+		REG_PBCR_H4_CTRL_IN_OUT = 0x20, // H4 sense always cleared if set
+		REG_PBCR_H4_CTRL_OUT_00 = 0x20, // H4 output negated
+		REG_PBCR_H4_CTRL_OUT_01 = 0x28, // H4 output asserted
+		REG_PBCR_H4_CTRL_OUT_10 = 0x30, // H4 output in interlocked input handshake protocol
+		REG_PBCR_H4_CTRL_OUT_11 = 0x38, // H4 output in pulsed input handshake protocol
+		REG_PBCR_H4_INT_ENABLE  = 0x04,
+		REG_PBCR_H3_SVCRQ_ENABLE= 0x02,
+		REG_PBCR_H3_STATUS_CTRL = 0x01,
+	};
+
+	enum {
+		REG_PCDR_TIN_BIT        = 2,   // BIT number
+		REG_PCDR_TIN            = 0x04 // bit position
+	};
+
 	enum {
+		REG_TCR_TIMER_ENABLE    = 0x01
+	};
+
+	enum { // TCR - Timer Control register
 		REG_TCR_ENABLE          = 0x01,
 		REG_TCR_CC_MASK         = 0x06,
 		REG_TCR_CC_PC2_CLK_PSC  = 0x00,
@@ -193,11 +293,18 @@ protected:
 		REG_TCR_TOUT_PC7_INT    = 0xe0, // 1 1 1
 	};
 
+	void tick_clock();
+
 	// device-level overrides
 	virtual void device_start () override;
 	virtual void device_reset () override;
 	virtual void device_timer (emu_timer &timer, device_timer_id id, int param, void *ptr) override;
 
+	// Interrupt methods
+	void trigger_interrupt(int source);
+	uint8_t irq_tiack();
+	uint8_t irq_piack();
+
 	int m_icount;
 
 	devcb_write8        m_pa_out_cb;
@@ -210,8 +317,10 @@ protected:
 	devcb_write_line    m_h2_out_cb;
 	devcb_write_line    m_h3_out_cb;
 	devcb_write_line    m_h4_out_cb;
+	devcb_write_line    m_tirq_out_cb;
+	devcb_write_line    m_pirq_out_cb;
 
-	// peripheral ports
+	// registers
 	uint8_t m_pgcr;           // Port General Control register
 	uint8_t m_psrr;           // Port Service Request register
 	uint8_t m_paddr;          // Port A Data Direction register
@@ -224,11 +333,18 @@ protected:
 	uint8_t m_pbdr;           // Port B Data register
 	uint8_t m_pcdr;           // Port C Data register
 	uint8_t m_psr;            // Port Status Register
-	uint8_t m_tcr;        // Timer Control Register
-	uint8_t m_tivr;       // Timer Interrupt Vector register
-	int m_cpr;          // Counter Preload Registers (3 x 8 = 24 bits)
-	int   m_cntr;       // - The 24 bit Counter
-	uint8_t m_tsr;        // Timer Status Register
+	uint8_t m_tcr;            // Timer Control Register
+	uint8_t m_tivr;           // Timer Interrupt Vector register
+	int     m_cpr;            // Counter Preload Registers (3 x 8 = 24 bits)
+	int     m_cntr;           // - The 24 bit Counter
+	uint8_t m_tsr;            // Timer Status Register
+
+
+	// Interrupt sources
+	enum
+	{
+		INT_TIMER
+	};
 
 	// Timers
 	emu_timer *pit_timer;
diff --git a/src/devices/machine/6840ptm.cpp b/src/devices/machine/6840ptm.cpp
index 3e5858b..7532d47 100644
--- a/src/devices/machine/6840ptm.cpp
+++ b/src/devices/machine/6840ptm.cpp
@@ -71,7 +71,6 @@ const device_type PTM6840 = &device_creator<ptm6840_device>;
 
 ptm6840_device::ptm6840_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
 	: device_t(mconfig, PTM6840, "6840 PTM", tag, owner, clock, "ptm6840", __FILE__),
-		m_internal_clock(0.0),
 		m_out_cb{*this, *this, *this},
 		m_irq_cb(*this)
 {
@@ -112,7 +111,6 @@ void ptm6840_device::device_start()
 	save_item(NAME(m_status_reg));
 	save_item(NAME(m_t3_divisor));
 	save_item(NAME(m_t3_scaler));
-	save_item(NAME(m_internal_clock));
 	save_item(NAME(m_irq));
 
 	save_item(NAME(m_control_reg));
@@ -170,17 +168,8 @@ void ptm6840_device::device_timer(emu_timer &timer, device_timer_id id, int para
 
 void ptm6840_device::subtract_from_counter(int counter, int count)
 {
-	double clock;
-
 	// Determine the clock frequency for this timer
-	if (m_control_reg[counter] & INTERNAL_CLK_EN)
-	{
-		clock = m_internal_clock;
-	}
-	else
-	{
-		clock = m_external_clock[counter];
-	}
+	double clk = m_control_reg[counter] & INTERNAL_CLK_EN ? static_cast<double>(clock()) : m_external_clock[counter];
 
 	// Dual-byte mode
 	if (m_control_reg[counter] & COUNT_MODE_8BIT)
@@ -234,7 +223,7 @@ void ptm6840_device::subtract_from_counter(int counter, int count)
 
 	if (m_enabled[counter])
 	{
-		attotime duration = attotime::from_hz(clock) * m_counter[counter];
+		attotime duration = attotime::from_hz(clk) * m_counter[counter];
 
 		if (counter == 2)
 		{
@@ -306,7 +295,7 @@ void ptm6840_device::update_interrupts()
 
 uint16_t ptm6840_device::compute_counter( int counter ) const
 {
-	double clock;
+	double clk;
 
 	// If there's no timer, return the count
 	if (!m_enabled[counter])
@@ -318,16 +307,16 @@ uint16_t ptm6840_device::compute_counter( int counter ) const
 	// determine the clock frequency for this timer
 	if (m_control_reg[counter] & INTERNAL_CLK_EN)
 	{
-		clock = m_internal_clock;
-		PLOG(("MC6840 #%s: %d internal clock freq %f \n", tag(), counter, clock));
+		clk = static_cast<double>(clock());
+		PLOG(("MC6840 #%s: %d internal clock freq %f \n", tag(), counter, clk));
 	}
 	else
 	{
-		clock = m_external_clock[counter];
-		PLOG(("MC6840 #%s: %d external clock freq %f \n", tag(), counter, clock));
+		clk = m_external_clock[counter];
+		PLOG(("MC6840 #%s: %d external clock freq %f \n", tag(), counter, clk));
 	}
 	// See how many are left
-	int remaining = (m_timer[counter]->remaining() * clock).as_double();
+	int remaining = (m_timer[counter]->remaining() * clk).as_double();
 
 	// Adjust the count for dual byte mode
 	if (m_control_reg[counter] & COUNT_MODE_8BIT)
@@ -349,7 +338,7 @@ uint16_t ptm6840_device::compute_counter( int counter ) const
 
 void ptm6840_device::reload_count(int idx)
 {
-	double clock;
+	double clk;
 
 	// Copy the latched value in
 	m_counter[idx] = m_latch[idx];
@@ -361,13 +350,13 @@ void ptm6840_device::reload_count(int idx)
 	// Determine the clock frequency for this timer
 	if (m_control_reg[idx] & INTERNAL_CLK_EN)
 	{
-		clock = m_internal_clock;
-		PLOG(("MC6840 #%s: %d internal clock freq %f \n", tag(), idx, clock));
+		clk = static_cast<double> (clock());
+		PLOG(("MC6840 #%s: %d internal clock freq %f \n", tag(), idx, clk));
 	}
 	else
 	{
-		clock = m_external_clock[idx];
-		PLOG(("MC6840 #%s: %d external clock freq %f \n", tag(), idx, clock));
+		clk = m_external_clock[idx];
+		PLOG(("MC6840 #%s: %d external clock freq %f \n", tag(), idx, clk));
 	}
 
 	// Determine the number of clock periods before we expire
@@ -390,9 +379,9 @@ void ptm6840_device::reload_count(int idx)
 	}
 
 	// Set the timer
-	PLOG(("MC6840 #%s: reload_count(%d): clock = %f  count = %d\n", tag(), idx, clock, count));
+	PLOG(("MC6840 #%s: reload_count(%d): clock = %f  count = %d\n", tag(), idx, clk, count));
 
-	attotime duration = attotime::from_hz(clock) * count;
+	attotime duration = attotime::from_hz(clk) * count;
 	if (idx == 2)
 	{
 		duration *= m_t3_divisor;
diff --git a/src/devices/machine/6840ptm.h b/src/devices/machine/6840ptm.h
index e567a64..d07586a 100644
--- a/src/devices/machine/6840ptm.h
+++ b/src/devices/machine/6840ptm.h
@@ -21,9 +21,6 @@
 //  DEVICE CONFIGURATION MACROS
 //**************************************************************************
 
-#define MCFG_PTM6840_INTERNAL_CLOCK(_clk) \
-	ptm6840_device::set_internal_clock(*device, _clk);
-
 #define MCFG_PTM6840_EXTERNAL_CLOCKS(_clk0, _clk1, _clk2) \
 	ptm6840_device::set_external_clocks(*device, _clk0, _clk1, _clk2);
 
@@ -51,7 +48,6 @@ public:
 	// construction/destruction
 	ptm6840_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
 
-	static void set_internal_clock(device_t &device, double clock) { downcast<ptm6840_device &>(device).m_internal_clock = clock; }
 	static void set_external_clocks(device_t &device, double clock0, double clock1, double clock2) { downcast<ptm6840_device &>(device).m_external_clock[0] = clock0; downcast<ptm6840_device &>(device).m_external_clock[1] = clock1; downcast<ptm6840_device &>(device).m_external_clock[2] = clock2; }
 	template<class _Object> static devcb_base &set_out_callback(device_t &device, int index, _Object object) { return downcast<ptm6840_device &>(device).m_out_cb[index].set_callback(object); }
 	template<class _Object> static devcb_base &set_irq_callback(device_t &device, _Object object) { return downcast<ptm6840_device &>(device).m_irq_cb.set_callback(object); }
@@ -125,7 +121,6 @@ private:
 		ANY_IRQ     = 0x80
 	};
 
-	double m_internal_clock;
 	double m_external_clock[3];
 
 	devcb_write_line m_out_cb[3];
diff --git a/src/devices/machine/74157.cpp b/src/devices/machine/74157.cpp
new file mode 100644
index 0000000..88f7b1d
--- /dev/null
+++ b/src/devices/machine/74157.cpp
@@ -0,0 +1,219 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+/***************************************************************************
+
+    74LS157/74HCT157 Quad 2 to 1-Line Data Selectors/Multiplexers (TTL)
+
+    Often used to help feed 8-bit ROM data into a MSM5205, and for many
+    other purposes.
+
+    74LS158 has inverted outputs; 74LS157 is non-inverting.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "74157.h"
+
+
+//**************************************************************************
+//  74LS157 DEVICE
+//**************************************************************************
+
+const device_type LS157 = &device_creator<ls157_device>;
+
+//-------------------------------------------------
+//  ls157_device - constructor
+//-------------------------------------------------
+
+ls157_device::ls157_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+	: ls157_device(mconfig, LS157, "74LS157 Quad 2-to-1 Multiplexer", tag, owner, clock, "74ls157", __FILE__)
+{
+}
+
+ls157_device::ls157_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, u32 clock, const char *shortname, const char *source)
+	: device_t(mconfig, type, name, tag, owner, clock, shortname, source)
+	, m_out_cb(*this)
+{
+	m_a = 0;
+	m_b = 0;
+	m_select = false;
+	m_strobe = false;
+}
+
+
+//-------------------------------------------------
+//  device_start - perform device-specific
+//  startup
+//-------------------------------------------------
+
+void ls157_device::device_start()
+{
+	// resolve callbacks
+	m_out_cb.resolve_safe();
+
+	// register items for save state
+	save_item(NAME(m_a));
+	save_item(NAME(m_b));
+	save_item(NAME(m_select));
+	save_item(NAME(m_strobe));
+}
+
+
+//**************************************************************************
+//  DATA INPUTS
+//**************************************************************************
+
+//-------------------------------------------------
+//  a_w -- write nibble to A1-A4
+//-------------------------------------------------
+
+WRITE8_MEMBER(ls157_device::a_w)
+{
+	a_w(data);
+}
+
+void ls157_device::a_w(u8 data)
+{
+	m_a = data & 0xf;
+	update_output();
+}
+
+
+//-------------------------------------------------
+//  b_w -- write nibble to B1-B4
+//-------------------------------------------------
+
+WRITE8_MEMBER(ls157_device::b_w)
+{
+	b_w(data);
+}
+
+void ls157_device::b_w(u8 data)
+{
+	m_b = data & 0xf;
+	update_output();
+}
+
+
+//-------------------------------------------------
+//  ab_w -- write high nibble to A1-A4 and write
+//  low nibble to B1-B4
+//-------------------------------------------------
+
+WRITE8_MEMBER(ls157_device::ab_w)
+{
+	ab_w(data);
+}
+
+void ls157_device::ab_w(u8 data)
+{
+	m_a = data >> 4;
+	m_b = data & 0xf;
+	update_output();
+}
+
+
+//-------------------------------------------------
+//  ba_w -- write high nibble to B1-B4 and write
+//  low nibble to A1-A4
+//-------------------------------------------------
+
+WRITE8_MEMBER(ls157_device::ba_w)
+{
+	ba_w(data);
+}
+
+void ls157_device::ba_w(u8 data)
+{
+	m_b = data >> 4;
+	m_a = data & 0xf;
+	update_output();
+}
+
+
+//-------------------------------------------------
+//  interleave_w -- write even-numbered bits to
+//  A1-A4 and write odd-numbered bits to B1-B4
+//-------------------------------------------------
+
+WRITE8_MEMBER(ls157_device::interleave_w)
+{
+	interleave_w(data);
+}
+
+void ls157_device::interleave_w(u8 data)
+{
+	m_b = ((data >> 4) & 8)
+		| ((data >> 3) & 4)
+		| ((data >> 2) & 2)
+		| ((data >> 1) & 1);
+	m_a = ((data >> 3) & 8)
+		| ((data >> 2) & 4)
+		| ((data >> 1) & 2)
+		| ((data >> 0) & 1);
+	update_output();
+}
+
+
+//**************************************************************************
+//  CONTROL LINE INPUTS
+//**************************************************************************
+
+//-------------------------------------------------
+//  select_w -- set select input
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER(ls157_device::select_w)
+{
+	if (m_select != bool(state))
+	{
+		m_select = bool(state);
+		update_output();
+	}
+}
+
+
+//-------------------------------------------------
+//  strobe_w -- set strobe input (active low)
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER(ls157_device::strobe_w)
+{
+	if (m_strobe != bool(state))
+	{
+		m_strobe = bool(state);
+
+		// Clear output when strobe goes high
+		if (m_strobe)
+			m_out_cb(0);
+		else
+			m_out_cb(m_select ? m_b : m_a);
+	}
+}
+
+
+//-------------------------------------------------
+//  update_output -- update output lines Y1-Y4
+//  unless strobe is high
+//-------------------------------------------------
+
+void ls157_device::update_output()
+{
+	// S high, strobe low: Y1-Y4 = B1-B4
+	// S low, strobe low:  Y1-Y4 = A1-A4
+	if (!m_strobe)
+		m_out_cb(m_select ? m_b : m_a);
+}
+
+
+//**************************************************************************
+//  74HCT157 DEVICE
+//**************************************************************************
+
+const device_type HCT157 = &device_creator<hct157_device>;
+
+hct157_device::hct157_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+	: ls157_device(mconfig, HCT157, "74HCT157 Quad 2-to-1 Multiplexer", tag, owner, clock, "74hct157", __FILE__)
+{
+}
diff --git a/src/devices/machine/74157.h b/src/devices/machine/74157.h
new file mode 100644
index 0000000..0a677e5
--- /dev/null
+++ b/src/devices/machine/74157.h
@@ -0,0 +1,104 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+/***************************************************************************
+
+    74LS157 Quad 2-Line to 1-Line Data Selectors/Multiplexers (TTL)
+
+****************************************************************************
+                                ____   ____
+                    SELECT   1 |*   \_/    | 16  Vcc
+                    A1 IN    2 |           | 15  STROBE
+                    B1 IN    3 |           | 14  A4 IN
+                    Y1 OUT   4 |           | 13  B4 IN
+                    A2 IN    5 |  74LS157  | 12  Y4 OUT
+                    B2 IN    6 |           | 11  A3 IN
+                    Y2 OUT   7 |           | 10  B3 IN
+                    GND      8 |___________|  9  Y3 OUT
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef DEVICES_MACHINE_74157_H
+#define DEVICES_MACHINE_74157_H
+
+#include "emu.h"
+
+
+//**************************************************************************
+//  DEVICE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_74157_OUT_CB(_devcb) \
+	devcb = &ls157_device::set_out_callback(*device, DEVCB_##_devcb);
+
+
+//**************************************************************************
+//  TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> ls157_device
+
+class ls157_device : public device_t
+{
+public:
+	// construction/destruction
+	ls157_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+	ls157_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, u32 clock, const char *shortname, const char *source);
+
+	// static configuration
+	template<class _Object> static devcb_base &set_out_callback(device_t &device, _Object object) { return downcast<ls157_device &>(device).m_out_cb.set_callback(object); }
+
+	// data writes
+	DECLARE_WRITE8_MEMBER(a_w);
+	void a_w(u8 data);
+	DECLARE_WRITE8_MEMBER(b_w);
+	void b_w(u8 data);
+	DECLARE_WRITE8_MEMBER(ab_w);
+	void ab_w(u8 data);
+	DECLARE_WRITE8_MEMBER(ba_w);
+	void ba_w(u8 data);
+	DECLARE_WRITE8_MEMBER(interleave_w);
+	void interleave_w(u8 data);
+
+	// line writes
+	DECLARE_WRITE_LINE_MEMBER(select_w);
+	DECLARE_WRITE_LINE_MEMBER(strobe_w);
+
+protected:
+	// device-level overrides
+	virtual void device_start() override;
+
+private:
+	// internal helpers
+	void update_output();
+
+	// callbacks
+	devcb_write8    m_out_cb;
+
+	// internal state
+	u8              m_a;
+	u8              m_b;
+	bool            m_select;
+	bool            m_strobe;
+};
+
+class hct157_device : public ls157_device
+{
+public:
+	// construction/destruction
+	hct157_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
+
+
+//**************************************************************************
+//  GLOBAL VARIABLES
+//**************************************************************************
+
+// device type definition
+extern const device_type LS157;
+extern const device_type HCT157;
+
+
+#endif
diff --git a/src/devices/machine/82s129.cpp b/src/devices/machine/82s129.cpp
index afc368a..f8f8b75 100644
--- a/src/devices/machine/82s129.cpp
+++ b/src/devices/machine/82s129.cpp
@@ -2,7 +2,7 @@
 // copyright-holders:Ryan Holtz
 /*****************************************************************************
 
-    (DM)9334 8-Bit Addressable Latch
+    82S129/6 1K-bit TTL bipolar PROM
 
 *****************************************************************************/
 
diff --git a/src/devices/machine/atahle.cpp b/src/devices/machine/atahle.cpp
index df2714d..344b305 100644
--- a/src/devices/machine/atahle.cpp
+++ b/src/devices/machine/atahle.cpp
@@ -852,7 +852,7 @@ WRITE16_MEMBER( ata_hle_device::write_cs0 )
 
 			/* sector count */
 			case IDE_CS0_SECTOR_COUNT_RW:
-				m_sector_count = data ? data : 256;
+				m_sector_count = (data & 0xff) ? (data & 0xff) : 0x100;
 				break;
 
 			/* current sector */
diff --git a/src/devices/machine/cdp1879.cpp b/src/devices/machine/cdp1879.cpp
new file mode 100644
index 0000000..4d0b588
--- /dev/null
+++ b/src/devices/machine/cdp1879.cpp
@@ -0,0 +1,152 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont,Carl
+/**********************************************************************
+
+    cdp1879.c - RCA CDP1879 real-time clock emulation
+
+**********************************************************************/
+
+#include "cdp1879.h"
+#include "machine/timehelp.h"
+
+//**************************************************************************
+//  LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type CDP1879 = &device_creator<cdp1879_device>;
+
+//-------------------------------------------------
+//  cdp1879_device - constructor
+//-------------------------------------------------
+
+cdp1879_device::cdp1879_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+	: device_t(mconfig, CDP1879, "RCA CDP1879", tag, owner, clock, "cdp1879", __FILE__),
+		device_rtc_interface(mconfig, *this),
+		m_irq_w(*this)
+{
+}
+
+
+//-------------------------------------------------
+//  device_start - device-specific startup
+//-------------------------------------------------
+
+void cdp1879_device::device_start()
+{
+	// allocate timers
+	m_clock_timer = timer_alloc();
+	m_clock_timer->adjust(attotime::from_seconds(1), 0, attotime::from_seconds(1));
+
+	m_irq_w.resolve_safe();
+
+	// state saving
+	save_item(NAME(m_regs));
+	save_item(NAME(m_comparator_state));
+}
+
+
+//-------------------------------------------------
+//  device_reset - device-specific reset
+//-------------------------------------------------
+
+void cdp1879_device::device_reset()
+{
+	m_regs[0] = m_regs[1] = 0;
+	m_regs[R_CTL_IRQSTATUS] = 0;
+	m_regs[R_CTL_CONTROL] = 0;
+	m_comparator_state = false;
+}
+
+
+//-------------------------------------------------
+//  device_timer - handler timer events
+//-------------------------------------------------
+
+void cdp1879_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+	advance_seconds();
+
+	// comparator IRQ
+	bool new_state = true;
+	for (int i = R_CNT_SECONDS; i <= R_CNT_MONTH; i++)
+	{
+		if(m_regs[i] != m_regs[i + 6])
+		{
+			new_state = false;
+			break;
+		}
+	}
+
+	if (!m_comparator_state && new_state)  // positive-edge-triggered
+		set_irq(7);
+
+	m_comparator_state = new_state;
+}
+
+
+//-------------------------------------------------
+//  rtc_clock_updated -
+//-------------------------------------------------
+
+void cdp1879_device::rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second)
+{
+	m_regs[R_CNT_SECONDS] = time_helper::make_bcd(second);           // seconds (BCD)
+	m_regs[R_CNT_MINUTES] = time_helper::make_bcd(minute);           // minutes (BCD)
+	m_regs[R_CNT_HOURS] = time_helper::make_bcd(hour);               // hour (BCD)
+	m_regs[R_CNT_DAYOFMONTH] = time_helper::make_bcd(day);           // day of the month (BCD)
+	m_regs[R_CNT_MONTH] = time_helper::make_bcd(month);              // month (BCD)
+}
+
+void cdp1879_device::set_irq(int bit)
+{
+	m_regs[R_CTL_IRQSTATUS] |= (1 << bit);
+	m_irq_w(ASSERT_LINE);
+}
+
+void cdp1879_device::update_rtc()
+{
+	set_clock_register(RTC_SECOND, bcd_to_integer(m_regs[R_CNT_SECONDS]));
+	set_clock_register(RTC_MINUTE, bcd_to_integer(m_regs[R_CNT_MINUTES]));
+	set_clock_register(RTC_HOUR, bcd_to_integer(m_regs[R_CNT_HOURS]));
+	set_clock_register(RTC_DAY, bcd_to_integer(m_regs[R_CNT_DAYOFMONTH]));
+	set_clock_register(RTC_MONTH, bcd_to_integer(m_regs[R_CNT_MONTH]));
+}
+
+READ8_MEMBER(cdp1879_device::read)
+{
+	if (offset == R_CTL_IRQSTATUS && !space.debugger_access())
+	{
+		// reading the IRQ status clears IRQ line and IRQ status
+		uint8_t data = m_regs[offset];
+		m_regs[R_CTL_IRQSTATUS] = 0;
+		m_irq_w(CLEAR_LINE);
+		return data;
+	}
+
+	return m_regs[offset];
+}
+
+WRITE8_MEMBER(cdp1879_device::write)
+{
+	switch (offset)
+	{
+		case R_CNT_SECONDS:
+		case R_CNT_MINUTES:
+		case R_CNT_HOURS:
+			if(BIT(m_regs[R_CTL_CONTROL], 3))
+			{
+				m_regs[offset + 6] = data;
+				break;
+			}
+		case R_CNT_DAYOFMONTH:
+		case R_CNT_MONTH:
+			m_regs[offset] = data;
+			update_rtc();
+			break;
+
+		case R_CTL_CONTROL:
+			m_regs[offset] = data;
+			break;
+	}
+}
diff --git a/src/devices/machine/cdp1879.h b/src/devices/machine/cdp1879.h
new file mode 100644
index 0000000..ed45bd9
--- /dev/null
+++ b/src/devices/machine/cdp1879.h
@@ -0,0 +1,85 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont,Carl
+/**********************************************************************
+
+    cdp1879.h - RCA CDP1879 real-time clock emulation
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __CDP1879_H__
+#define __CDP1879_H__
+
+#include "emu.h"
+#include "dirtc.h"
+
+
+//**************************************************************************
+//  INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_CDP1879_IRQ_CALLBACK(_cb) \
+	devcb = &cdp1879_device::set_irq_cb(*device, DEVCB_##_cb);
+
+
+//**************************************************************************
+//  TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> cdp1879_device
+
+class cdp1879_device :  public device_t,
+						public device_rtc_interface
+{
+public:
+	// construction/destruction
+	cdp1879_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+	DECLARE_READ8_MEMBER(read);
+	DECLARE_WRITE8_MEMBER(write);
+
+	template<class _Object> static devcb_base &set_irq_cb(device_t &device, _Object wr) { return downcast<cdp1879_device &>(device).m_irq_w.set_callback(wr); }
+
+	devcb_write_line m_irq_w;
+
+protected:
+	// device-level overrides
+	virtual void device_start() override;
+	virtual void device_reset() override;
+	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+
+	// device_rtc_interface overrides
+	virtual void rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second) override;
+	virtual bool rtc_feature_leap_year() const override { return true; }
+
+	void set_irq(int bit);
+	void update_rtc();
+
+private:
+	// registers
+	enum
+	{
+		R_CNT_SECONDS = 2,      // 2 = seconds
+		R_CNT_MINUTES,          // 3 = minutes
+		R_CNT_HOURS,            // 4 = hours
+		R_CNT_DAYOFMONTH,       // 5 = day of the month
+		R_CNT_MONTH,            // 6 = month
+		R_CTL_IRQSTATUS = 7,    // 7 = IRQ status
+		R_CTL_CONTROL = 7,   // 7 = IRQ control
+		R_ALM_SECONDS,
+		R_ALM_MINUTES,
+		R_ALM_HOURS
+	};
+
+	u8 m_regs[10];
+	bool m_comparator_state;
+
+	// timers
+	emu_timer *m_clock_timer;
+};
+
+// device type definition
+extern const device_type CDP1879;
+
+#endif
diff --git a/src/devices/machine/genpc.cpp b/src/devices/machine/genpc.cpp
index 9a44c04..af575f6 100644
--- a/src/devices/machine/genpc.cpp
+++ b/src/devices/machine/genpc.cpp
@@ -281,7 +281,7 @@ WRITE_LINE_MEMBER( ibm5160_mb_device::keyboard_clock_w )
 		m_ppi_shift_register |= m_ppi_data_signal << 7;
 
 		m_pic8259->ir1_w(m_ppi_shift_enable);
-		m_pc_kbdc->data_write_from_mb(!BIT(m_ppi_portb, 2) && !m_ppi_shift_enable);
+		m_pc_kbdc->data_write_from_mb(!m_ppi_shift_enable);
 	}
 }
 
@@ -365,7 +365,7 @@ WRITE8_MEMBER( ibm5160_mb_device::pc_ppi_portb_w )
 		m_pic8259->ir1_w(m_ppi_shift_enable);
 	}
 
-	m_pc_kbdc->data_write_from_mb(!BIT(m_ppi_portb, 2) && !m_ppi_shift_enable);
+	m_pc_kbdc->data_write_from_mb(!m_ppi_shift_enable);
 	m_ppi_clock_signal = ( m_ppi_keyb_clock ) ? 1 : 0;
 	m_pc_kbdc->clock_write_from_mb(m_ppi_clock_signal);
 }
diff --git a/src/devices/machine/i8155.cpp b/src/devices/machine/i8155.cpp
index 74989e5..aca3314 100644
--- a/src/devices/machine/i8155.cpp
+++ b/src/devices/machine/i8155.cpp
@@ -294,18 +294,9 @@ void i8155_device::device_timer(emu_timer &timer, device_timer_id id, int param,
 	{
 		if (LOG) logerror("8155 Timer Count Reached\n");
 
-		switch (m_command & COMMAND_TM_MASK)
-		{
-		case COMMAND_TM_STOP_AFTER_TC:
-			// stop timer
-			m_timer->enable(0);
-
-			if (LOG) logerror("8155 Timer Stopped\n");
-			break;
-		}
-
 		switch (get_timer_mode())
 		{
+		case TIMER_MODE_LOW:
 		case TIMER_MODE_SQUARE_WAVE:
 			// toggle timer output
 			m_to = !m_to;
@@ -313,15 +304,8 @@ void i8155_device::device_timer(emu_timer &timer, device_timer_id id, int param,
 			break;
 
 		case TIMER_MODE_SINGLE_PULSE:
-			// single pulse upon TC being reached
-			pulse_timer_output();
-
-			// clear timer mode setting
-			m_command &= ~COMMAND_TM_MASK;
-			break;
-
 		case TIMER_MODE_AUTOMATIC_RELOAD:
-			// automatic reload, i.e. single pulse every time TC is reached
+			// pulse upon TC being reached
 			pulse_timer_output();
 			break;
 		}
@@ -329,8 +313,28 @@ void i8155_device::device_timer(emu_timer &timer, device_timer_id id, int param,
 		// set timer flag
 		m_status |= STATUS_TIMER;
 
-		// reload timer counter
-		m_counter = m_count_length & 0x3fff;
+		if ((m_command & COMMAND_TM_MASK) == COMMAND_TM_START)
+		{
+			// load new timer counter
+			m_counter = m_count_length & 0x3fff;
+
+			if (LOG) logerror("8155 Timer New Start\n");
+		}
+		else if ((m_command & COMMAND_TM_MASK) == COMMAND_TM_STOP_AFTER_TC || get_timer_mode() == TIMER_MODE_SINGLE_PULSE)
+		{
+			// stop timer
+			m_timer->enable(0);
+
+			if (LOG) logerror("8155 Timer Stopped\n");
+		}
+		else
+		{
+			// automatically reload the counter
+			m_counter = m_count_length & 0x3fff;
+		}
+
+		// clear timer command
+		m_command &= ~COMMAND_TM_MASK;
 	}
 }
 
@@ -455,6 +459,9 @@ void i8155_device::register_w(int offset, uint8_t data)
 				// load mode and CNT length and start immediately after loading (if timer is not running)
 				m_counter = m_count_length & 0x3fff;
 				m_timer->adjust(attotime::zero, 0, attotime::from_hz(clock()));
+
+				// clear timer command so this won't execute twice
+				m_command &= ~COMMAND_TM_MASK;
 			}
 			break;
 		}
diff --git a/src/devices/machine/idehd.cpp b/src/devices/machine/idehd.cpp
index 35e90f6..59ca41e 100644
--- a/src/devices/machine/idehd.cpp
+++ b/src/devices/machine/idehd.cpp
@@ -678,7 +678,7 @@ void ata_mass_storage_device::process_command()
 			(m_cylinder_high << 8) | m_cylinder_low, m_device_head & IDE_DEVICE_HEAD_HS, m_sector_number, lba_address(), m_sector_count));
 
 		/* reset the buffer */
-		m_sectors_until_int = 1;
+		m_sectors_until_int = m_block_count;
 
 		/* mark the buffer ready */
 		m_status |= IDE_STATUS_DRQ;
diff --git a/src/devices/machine/laserdsc.cpp b/src/devices/machine/laserdsc.cpp
index 824779c..b090b23 100644
--- a/src/devices/machine/laserdsc.cpp
+++ b/src/devices/machine/laserdsc.cpp
@@ -321,7 +321,7 @@ void laserdisc_device::device_start()
 	init_audio();
 
 	// register callbacks
-	machine().configuration().config_register("laserdisc", config_saveload_delegate(&laserdisc_device::config_load, this), config_saveload_delegate(&laserdisc_device::config_save, this));
+	machine().configuration().config_register("laserdisc", config_load_delegate(&laserdisc_device::config_load, this), config_save_delegate(&laserdisc_device::config_save, this));
 }
 
 
@@ -1142,10 +1142,10 @@ void laserdisc_device::process_track_data()
 //  configuration file
 //-------------------------------------------------
 
-void laserdisc_device::config_load(config_type cfg_type, xml_data_node *parentnode)
+void laserdisc_device::config_load(config_type cfg_type, util::xml::data_node const *parentnode)
 {
 	// we only care about game files
-	if (cfg_type != config_type::CONFIG_TYPE_GAME)
+	if (cfg_type != config_type::GAME)
 		return;
 
 	// might not have any data
@@ -1153,13 +1153,13 @@ void laserdisc_device::config_load(config_type cfg_type, xml_data_node *parentno
 		return;
 
 	// iterate over overlay nodes
-	for (xml_data_node const *ldnode = parentnode->get_child("device"); ldnode != nullptr; ldnode = ldnode->get_next_sibling("device"))
+	for (util::xml::data_node const *ldnode = parentnode->get_child("device"); ldnode != nullptr; ldnode = ldnode->get_next_sibling("device"))
 	{
 		const char *devtag = ldnode->get_attribute_string("tag", "");
 		if (strcmp(devtag, tag()) == 0)
 		{
 			// handle the overlay node
-			xml_data_node const *const overnode = ldnode->get_child("overlay");
+			util::xml::data_node const *const overnode = ldnode->get_child("overlay");
 			if (overnode != nullptr)
 			{
 				// fetch positioning controls
@@ -1178,21 +1178,21 @@ void laserdisc_device::config_load(config_type cfg_type, xml_data_node *parentno
 //  file
 //-------------------------------------------------
 
-void laserdisc_device::config_save(config_type cfg_type, xml_data_node *parentnode)
+void laserdisc_device::config_save(config_type cfg_type, util::xml::data_node *parentnode)
 {
 	// we only care about game files
-	if (cfg_type != config_type::CONFIG_TYPE_GAME)
+	if (cfg_type != config_type::GAME)
 		return;
 
 	// create a node
-	xml_data_node *const ldnode = parentnode->add_child("device", nullptr);
+	util::xml::data_node *const ldnode = parentnode->add_child("device", nullptr);
 	if (ldnode != nullptr)
 	{
 		// output the basics
 		ldnode->set_attribute("tag", tag());
 
 		// add an overlay node
-		xml_data_node *const overnode = ldnode->add_child("overlay", nullptr);
+		util::xml::data_node *const overnode = ldnode->add_child("overlay", nullptr);
 		bool changed = false;
 		if (overnode != nullptr)
 		{
diff --git a/src/devices/machine/laserdsc.h b/src/devices/machine/laserdsc.h
index ada53fd..b69dec3 100644
--- a/src/devices/machine/laserdsc.h
+++ b/src/devices/machine/laserdsc.h
@@ -286,8 +286,8 @@ private:
 	void read_track_data();
 	static void *read_async_static(void *param, int threadid);
 	void process_track_data();
-	void config_load(config_type cfg_type, xml_data_node *parentnode);
-	void config_save(config_type cfg_type, xml_data_node *parentnode);
+	void config_load(config_type cfg_type, util::xml::data_node const *parentnode);
+	void config_save(config_type cfg_type, util::xml::data_node *parentnode);
 
 	// configuration
 	laserdisc_get_disc_delegate m_getdisc_callback;
diff --git a/src/devices/machine/microtch.cpp b/src/devices/machine/microtch.cpp
index b8a810b..4f6d10c 100644
--- a/src/devices/machine/microtch.cpp
+++ b/src/devices/machine/microtch.cpp
@@ -120,10 +120,12 @@ void microtouch_device::device_timer(emu_timer &timer, device_timer_id id, int p
 
 	if ( m_tx_buffer_ptr < m_tx_buffer_num )
 	{
-		m_output = m_tx_buffer[m_tx_buffer_ptr++];
-		m_output_valid = true;
 		if(is_transmit_register_empty())
+		{
+			m_output = m_tx_buffer[m_tx_buffer_ptr++];
+			m_output_valid = true;
 			tra_complete();
+		}
 
 		if ( m_tx_buffer_ptr == m_tx_buffer_num )
 		{
@@ -263,6 +265,32 @@ void microtouch_device::rcv_complete()
 			m_rx_buffer_ptr = 0;
 			return;
 		}
+		else if ( check_command("OS", m_rx_buffer_ptr, m_rx_buffer ) )
+		{
+			// output status
+			m_tx_buffer[m_tx_buffer_num++] = 0x01;
+
+			// ---- ---x    RAM error
+			// ---- --x-    ROM error
+			// ---- -x--    Analog-to-digital error
+			// ---- x---    NOVRAM error
+			// ---x ----    ASIC error
+			// --x- ----    Power on flag
+			// -x-- ----    Always 1
+			// x--- ----    Always 0
+			m_tx_buffer[m_tx_buffer_num++] = 0x40;
+
+			// ---- ---x    Cable NOVRAM error
+			// ---- --x-    Hard NOVRAM error
+			// ---x xx--    Reserved
+			// --x- ----    Software reset flag
+			// -x-- ----    Always 1
+			// x--- ----    Always 0
+			m_tx_buffer[m_tx_buffer_num++] = 0x40 | (m_reset_done << 5);
+			m_tx_buffer[m_tx_buffer_num++] = 0x0d;
+			m_rx_buffer_ptr = 0;
+			return;
+		}
 		// send response
 		m_tx_buffer[m_tx_buffer_num++] = 0x01;
 		m_tx_buffer[m_tx_buffer_num++] = 0x30;
diff --git a/src/devices/machine/netlist.cpp b/src/devices/machine/netlist.cpp
index 3183f87..9f321b5 100644
--- a/src/devices/machine/netlist.cpp
+++ b/src/devices/machine/netlist.cpp
@@ -28,6 +28,8 @@ const device_type NETLIST_SOUND = &device_creator<netlist_mame_sound_device_t>;
 
 const device_type NETLIST_ANALOG_INPUT = &device_creator<netlist_mame_analog_input_t>;
 const device_type NETLIST_INT_INPUT = &device_creator<netlist_mame_int_input_t>;
+const device_type NETLIST_ROM_REGION = &device_creator<netlist_mame_rom_t>;
+const device_type NETLIST_RAM_POINTER = &device_creator<netlist_ram_pointer_t>;
 const device_type NETLIST_LOGIC_INPUT = &device_creator<netlist_mame_logic_input_t>;
 const device_type NETLIST_STREAM_INPUT = &device_creator<netlist_mame_stream_input_t>;
 
@@ -83,7 +85,7 @@ void netlist_mame_analog_input_t::device_start()
 // ----------------------------------------------------------------------------------------
 
 netlist_mame_analog_output_t::netlist_mame_analog_output_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
-		: device_t(mconfig, NETLIST_ANALOG_INPUT, "Netlist Analog Output", tag, owner, clock, "netlist_analog_output", __FILE__),
+		: device_t(mconfig, NETLIST_ANALOG_OUTPUT, "Netlist Analog Output", tag, owner, clock, "netlist_analog_output", __FILE__),
 			netlist_mame_sub_interface(*owner),
 			m_in("")
 {
@@ -118,7 +120,7 @@ void netlist_mame_analog_output_t::device_start()
 // ----------------------------------------------------------------------------------------
 
 netlist_mame_int_input_t::netlist_mame_int_input_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
-		: device_t(mconfig, NETLIST_INT_INPUT, "Netlist Logic Input", tag, owner, clock, "netlist_logic_input", __FILE__),
+		: device_t(mconfig, NETLIST_INT_INPUT, "Netlist Integer Input", tag, owner, clock, "netlist_logic_input", __FILE__),
 			netlist_mame_sub_interface(*owner),
 			m_param(nullptr),
 			m_mask(0xffffffff),
@@ -180,6 +182,77 @@ void netlist_mame_logic_input_t::device_start()
 }
 
 // ----------------------------------------------------------------------------------------
+// netlist_mame_rom_t
+// ----------------------------------------------------------------------------------------
+
+netlist_mame_rom_t::netlist_mame_rom_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+		: device_t(mconfig, NETLIST_ROM_REGION, "Netlist ROM Region", tag, owner, clock, "netlist_rom_region", __FILE__)
+		, netlist_mame_sub_interface(*owner)
+		, m_param(nullptr)
+		, m_param_name("")
+		, m_data_tag(nullptr)
+		, m_data(nullptr)
+{
+}
+
+void netlist_mame_rom_t::static_set_params(device_t &device, const char *param_name, const char* data_tag)
+{
+	netlist_mame_rom_t &netlist = downcast<netlist_mame_rom_t&>(device);
+	LOG_DEV_CALLS(("static_set_params %s\n", device.tag()));
+	netlist.m_param_name = param_name;
+	netlist.m_data_tag = data_tag;
+}
+
+void netlist_mame_rom_t::device_start()
+{
+	LOG_DEV_CALLS(("start %s\n", tag()));
+	netlist::param_t *p = downcast<netlist_mame_device_t *>(this->owner())->setup().find_param(m_param_name);
+	m_param = dynamic_cast<netlist::param_ptr_t *>(p);
+	if (m_param == nullptr)
+	{
+		fatalerror("device %s wrong parameter type for %s\n", basetag(), m_param_name.cstr());
+	}
+
+	if (memregion(m_data_tag) != nullptr)
+		m_data = memregion(m_data_tag)->base();
+
+	m_param->setTo(m_data);
+}
+
+// ----------------------------------------------------------------------------------------
+// netlist_ram_pointer_t
+// ----------------------------------------------------------------------------------------
+
+netlist_ram_pointer_t::netlist_ram_pointer_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+		: device_t(mconfig, NETLIST_RAM_POINTER, "Netlist RAM Pointer", tag, owner, clock, "netlist_ram_pointer", __FILE__)
+		, netlist_mame_sub_interface(*owner)
+		, m_param(nullptr)
+		, m_param_name("")
+		, m_data(nullptr)
+{
+}
+
+void netlist_ram_pointer_t::static_set_params(device_t &device, const char *param_name)
+{
+	netlist_ram_pointer_t &netlist = downcast<netlist_ram_pointer_t&>(device);
+	LOG_DEV_CALLS(("static_set_params %s\n", device.tag()));
+	netlist.m_param_name = param_name;
+}
+
+void netlist_ram_pointer_t::device_start()
+{
+	LOG_DEV_CALLS(("start %s\n", tag()));
+	netlist::param_t *p = downcast<netlist_mame_device_t *>(this->owner())->setup().find_param(m_param_name);
+	m_param = dynamic_cast<netlist::param_ptr_t *>(p);
+	if (m_param == nullptr)
+	{
+		fatalerror("device %s wrong parameter type for %s\n", basetag(), m_param_name.cstr());
+	}
+
+	m_data = (*m_param)();
+}
+
+// ----------------------------------------------------------------------------------------
 // netlist_mame_stream_input_t
 // ----------------------------------------------------------------------------------------
 
diff --git a/src/devices/machine/netlist.h b/src/devices/machine/netlist.h
index 7d5d884..e4cee9a 100644
--- a/src/devices/machine/netlist.h
+++ b/src/devices/machine/netlist.h
@@ -35,14 +35,22 @@
 				netlist_analog_output_delegate(& _class :: _member,                 \
 						# _class "::" # _member, _class_tag, (_class *)nullptr)   );
 
-#define MCFG_NETLIST_LOGIC_INPUT(_basetag, _tag, _name, _shift)              \
-	MCFG_DEVICE_ADD(_basetag ":" _tag, NETLIST_LOGIC_INPUT, 0)                      \
+#define MCFG_NETLIST_LOGIC_INPUT(_basetag, _tag, _name, _shift)             \
+	MCFG_DEVICE_ADD(_basetag ":" _tag, NETLIST_LOGIC_INPUT, 0)              \
 	netlist_mame_logic_input_t::static_set_params(*device, _name, _shift);
 
-#define MCFG_NETLIST_INT_INPUT(_basetag, _tag, _name, _shift, _mask)                \
-	MCFG_DEVICE_ADD(_basetag ":" _tag, NETLIST_INT_INPUT, 0)                      \
+#define MCFG_NETLIST_INT_INPUT(_basetag, _tag, _name, _shift, _mask)        \
+	MCFG_DEVICE_ADD(_basetag ":" _tag, NETLIST_INT_INPUT, 0)                \
 	netlist_mame_int_input_t::static_set_params(*device, _name, _mask, _shift);
 
+#define MCFG_NETLIST_ROM_REGION(_basetag, _tag, _name, _region) \
+	MCFG_DEVICE_ADD(_basetag ":" _tag, NETLIST_ROM_REGION, 0) \
+	netlist_mame_rom_t::static_set_params(*device, _name ".m_ROM", ":" _region);
+
+#define MCFG_NETLIST_RAM_POINTER(_basetag, _tag, _name) \
+	MCFG_DEVICE_ADD(_basetag ":" _tag, NETLIST_RAM_POINTER, 0) \
+	netlist_ram_pointer_t::static_set_params(*device, _name ".m_RAM");
+
 #define MCFG_NETLIST_STREAM_INPUT(_basetag, _chan, _name)                           \
 	MCFG_DEVICE_ADD(_basetag ":cin" # _chan, NETLIST_STREAM_INPUT, 0)               \
 	netlist_mame_stream_input_t::static_set_params(*device, _chan, _name);
@@ -51,7 +59,6 @@
 	MCFG_DEVICE_ADD(_basetag ":cout" # _chan, NETLIST_STREAM_OUTPUT, 0)             \
 	netlist_mame_stream_output_t::static_set_params(*device, _chan, _name);
 
-
 #define NETLIST_LOGIC_PORT_CHANGED(_base, _tag)                                     \
 	PORT_CHANGED_MEMBER(_base ":" _tag, netlist_mame_logic_input_t, input_changed, 0)
 
@@ -410,13 +417,12 @@ private:
 	netlist_analog_output_delegate m_delegate;
 };
 
-
 // ----------------------------------------------------------------------------------------
 // netlist_mame_int_input_t
 // ----------------------------------------------------------------------------------------
 
 class netlist_mame_int_input_t :  public device_t,
-									public netlist_mame_sub_interface
+								  public netlist_mame_sub_interface
 {
 public:
 
@@ -457,6 +463,7 @@ private:
 	pstring m_param_name;
 };
 
+
 // ----------------------------------------------------------------------------------------
 // netlist_mame_logic_input_t
 // ----------------------------------------------------------------------------------------
@@ -503,6 +510,67 @@ private:
 };
 
 // ----------------------------------------------------------------------------------------
+// netlist_mame_rom_t
+// ----------------------------------------------------------------------------------------
+
+class netlist_mame_rom_t : public device_t,
+						   public netlist_mame_sub_interface
+{
+public:
+
+	// construction/destruction
+	netlist_mame_rom_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+	virtual ~netlist_mame_rom_t() { }
+
+	static void static_set_params(device_t &device, const char *param_name, const char* region_tag);
+
+protected:
+	// device-level overrides
+	virtual void device_start() override;
+	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override
+	{
+		m_param->setTo(m_data);
+	}
+
+private:
+	netlist::param_ptr_t *m_param;
+	pstring m_param_name;
+	const char* m_data_tag;
+	uint8_t* m_data;
+};
+
+// ----------------------------------------------------------------------------------------
+// netlist_ram_pointer_t
+// ----------------------------------------------------------------------------------------
+
+class netlist_ram_pointer_t: public device_t,
+							 public netlist_mame_sub_interface
+{
+public:
+
+	// construction/destruction
+	netlist_ram_pointer_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+	virtual ~netlist_ram_pointer_t() { }
+
+	uint8_t* ptr() const { return m_data; }
+
+	static void static_set_params(device_t &device, const char *param_name);
+
+protected:
+	// device-level overrides
+	virtual void device_start() override;
+	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override
+	{
+		m_data = (*m_param)();
+	}
+
+private:
+	netlist::param_ptr_t *m_param;
+	pstring m_param_name;
+	uint8_t* m_data;
+};
+
+// ----------------------------------------------------------------------------------------
 // netlist_mame_stream_input_t
 // ----------------------------------------------------------------------------------------
 
@@ -761,6 +829,8 @@ extern const device_type NETLIST_SOUND;
 extern const device_type NETLIST_ANALOG_INPUT;
 extern const device_type NETLIST_LOGIC_INPUT;
 extern const device_type NETLIST_INT_INPUT;
+extern const device_type NETLIST_ROM_REGION;
+extern const device_type NETLIST_RAM_POINTER;
 
 extern const device_type NETLIST_ANALOG_OUTPUT;
 extern const device_type NETLIST_STREAM_INPUT;
diff --git a/src/devices/machine/pci-ide.cpp b/src/devices/machine/pci-ide.cpp
index ab49e81..398831e 100644
--- a/src/devices/machine/pci-ide.cpp
+++ b/src/devices/machine/pci-ide.cpp
@@ -41,11 +41,11 @@ DEVICE_ADDRESS_MAP_START(bus_master_map, 32, ide_pci_device)
 ADDRESS_MAP_END
 
 static MACHINE_CONFIG_FRAGMENT(pci_ide)
-	MCFG_BUS_MASTER_IDE_CONTROLLER_ADD("ide", ata_devices, "hdd", nullptr, true)
+	MCFG_BUS_MASTER_IDE_CONTROLLER_ADD("ide", ata_devices, "hdd", "cdrom", true)
 	MCFG_ATA_INTERFACE_IRQ_HANDLER(WRITELINE(ide_pci_device, ide_interrupt))
 	//MCFG_BUS_MASTER_IDE_CONTROLLER_SPACE(":maincpu", AS_PROGRAM)
 	MCFG_BUS_MASTER_IDE_CONTROLLER_SPACE(":pci:00.0", AS_DATA)
-	MCFG_BUS_MASTER_IDE_CONTROLLER_ADD("ide2", ata_devices, nullptr, "cdrom", true)
+	MCFG_BUS_MASTER_IDE_CONTROLLER_ADD("ide2", ata_devices, "hdd", "cdrom", true)
 	MCFG_ATA_INTERFACE_IRQ_HANDLER(WRITELINE(ide_pci_device, ide_interrupt))
 	//MCFG_BUS_MASTER_IDE_CONTROLLER_SPACE(":maincpu", AS_PROGRAM)
 	MCFG_BUS_MASTER_IDE_CONTROLLER_SPACE(":pci:00.0", AS_DATA)
diff --git a/src/devices/machine/pci.cpp b/src/devices/machine/pci.cpp
index dd8e767..97b9e7b 100644
--- a/src/devices/machine/pci.cpp
+++ b/src/devices/machine/pci.cpp
@@ -284,7 +284,7 @@ void pci_device::map_device(uint64_t memory_window_start, uint64_t memory_window
 		case 5: space->install_readwrite_handler(start, end, read32_delegate(FUNC(pci_device::unmapped5_r), this), write32_delegate(FUNC(pci_device::unmapped5_w), this)); break;
 		}
 
-		space->install_device_delegate(start, end, *this, bi.map);
+		space->install_device_delegate(start, end, *bi.device, bi.map);
 		logerror("map %s at %0*x-%0*x\n", bi.map.name(), bi.flags & M_IO ? 4 : 8, uint32_t(start), bi.flags & M_IO ? 4 : 8, uint32_t(end));
 	}
 
@@ -317,11 +317,12 @@ void pci_device::skip_map_regs(int count)
 	assert(bank_reg_count <= 6);
 }
 
-void pci_device::add_map(uint64_t size, int flags, address_map_delegate &map)
+void pci_device::add_map(uint64_t size, int flags, address_map_delegate &map, device_t *relative_to)
 {
 	assert(bank_count < 6);
 	int bid = bank_count++;
 	bank_infos[bid].map = map;
+	bank_infos[bid].device = relative_to ? relative_to : this;
 	bank_infos[bid].adr = 0;
 	bank_infos[bid].size = size;
 	bank_infos[bid].flags = flags;
diff --git a/src/devices/machine/pci.h b/src/devices/machine/pci.h
index 6b94f4a..a67e17a 100644
--- a/src/devices/machine/pci.h
+++ b/src/devices/machine/pci.h
@@ -94,8 +94,8 @@ protected:
 	};
 
 	struct bank_info {
-		// One of the two
 		address_map_delegate map;
+		device_t *device;
 
 		uint64_t adr;
 		uint32_t size;
@@ -123,7 +123,7 @@ protected:
 	virtual void device_reset() override;
 
 	void skip_map_regs(int count);
-	void add_map(uint64_t size, int flags, address_map_delegate &map);
+	void add_map(uint64_t size, int flags, address_map_delegate &map, device_t *relative_to = nullptr);
 	template <typename T> void add_map(uint64_t size, int flags, void (T::*map)(address_map &map), const char *name) {
 		address_map_delegate delegate(map, name, static_cast<T *>(this));
 		add_map(size, flags, delegate);
diff --git a/src/devices/machine/pci9050.cpp b/src/devices/machine/pci9050.cpp
index 8f5e36b..dad3618 100644
--- a/src/devices/machine/pci9050.cpp
+++ b/src/devices/machine/pci9050.cpp
@@ -50,32 +50,22 @@ pci9050_device::pci9050_device(const machine_config &mconfig, const char *tag, d
 	}
 }
 
-void pci9050_device::set_map(int id, address_map_constructor map, const char *name, device_t *device)
+void pci9050_device::set_map(int id, const address_map_delegate &map, device_t *device)
 {
 	m_maps[id] = map;
-	m_names[id] = name;
 	m_devices[id] = device;
 }
 
 void pci9050_device::device_start()
 {
-	typedef void (pci9050_device::*tramp_t)(address_map &);
-	static const tramp_t trampolines[4] = {
-		&pci9050_device::map_trampoline<0>,
-		&pci9050_device::map_trampoline<1>,
-		&pci9050_device::map_trampoline<2>,
-		&pci9050_device::map_trampoline<3>
-	};
-
 	pci_device::device_start();
 
 	add_map(0x80, M_MEM, FUNC(pci9050_device::map));           // map 0 is our config registers, mem space
 	add_map(0x80, M_IO,  FUNC(pci9050_device::map));           // map 1 is our config registers, i/o space
 
 	for(int i=0; i<4; i++)
-		if(m_names[i])
-			//          add_map(0, M_MEM | M_DISABLED, m_maps[i], m_names[i], m_devices[i]);
-			add_map(0, M_MEM | M_DISABLED, trampolines[i], m_names[i]);
+		if(!m_maps[i].isnull())
+			add_map(0, M_MEM | M_DISABLED, m_maps[i], m_devices[i]);
 		else
 			add_map(0, M_MEM | M_DISABLED, FUNC(pci9050_device::empty));
 
diff --git a/src/devices/machine/pci9050.h b/src/devices/machine/pci9050.h
index f8ba288..ce33f35 100644
--- a/src/devices/machine/pci9050.h
+++ b/src/devices/machine/pci9050.h
@@ -17,7 +17,7 @@
 	MCFG_PCI_DEVICE_ADD(_tag, PCI9050, 0x10b59050, 0x01, 0x06800000, 0x10b59050)
 
 #define MCFG_PCI9050_SET_MAP(id, map) \
-	downcast<pci9050_device *>(device)->set_map(id, ADDRESS_MAP_NAME(map), #map, owner);
+	downcast<pci9050_device *>(device)->set_map(id, address_map_delegate(ADDRESS_MAP_NAME(map), #map), owner);
 
 #define MCFG_PCI9050_USER_INPUT_CALLBACK(_write) \
 	devcb = &pci9050_device::set_user_input_callback(*device, DEVCB_##_write);
@@ -29,7 +29,7 @@ class pci9050_device :
 	public pci_device
 {
 public:
-	pci9050_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+	pci9050_device(const machine_config &mconfig, const char *tag, device_t *device, uint32_t clock);
 
 	// PCI9050 I/O register space handlers
 	DECLARE_READ32_MEMBER( lasrr_r  );
@@ -54,7 +54,7 @@ public:
 	template<class _Object> static devcb_base &set_user_input_callback(device_t &device, _Object object) { return downcast<pci9050_device &>(device).m_user_input_handler.set_callback(object); }
 	template<class _Object> static devcb_base &set_user_output_callback(device_t &device, _Object object) { return downcast<pci9050_device &>(device).m_user_output_handler.set_callback(object); }
 
-	void set_map(int id, address_map_constructor map, const char *name, device_t *device);
+	void set_map(int id, const address_map_delegate &map, device_t *device);
 
 protected:
 	virtual void device_start() override;
@@ -67,7 +67,7 @@ private:
 
 	const char *m_names[4];
 	device_t *m_devices[4];
-	address_map_constructor m_maps[4];
+	address_map_delegate m_maps[4];
 
 	uint32_t m_lasrr[4], m_lasba[4], m_lasbrd[4], m_csbase[4];
 	uint32_t m_eromrr, m_eromba, m_erombrd, m_intcsr, m_cntrl;
@@ -75,10 +75,6 @@ private:
 	void remap_local(int id);
 	void remap_rom();
 
-	template<int id> void map_trampoline(address_map &map) {
-		m_maps[id](map);
-	}
-
 	devcb_read32 m_user_input_handler;
 	devcb_write32 m_user_output_handler;
 
diff --git a/src/devices/machine/pit8253.cpp b/src/devices/machine/pit8253.cpp
index 1cfb5d4..87f669b 100644
--- a/src/devices/machine/pit8253.cpp
+++ b/src/devices/machine/pit8253.cpp
@@ -724,7 +724,7 @@ void pit8253_device::update(pit8253_timer *timer)
 	attotime elapsed_time = now - timer->last_updated;
 	int64_t elapsed_cycles = elapsed_time.as_double() * timer->clockin;
 
-	LOG1(("update(): timer %d, %d elapsed_cycles\n", timer->index, elapsed_cycles));
+	LOG2(("update(): timer %d, %d elapsed_cycles\n", timer->index, elapsed_cycles));
 
 	if (timer->clockin)
 		timer->last_updated += elapsed_cycles * attotime::from_hz(timer->clockin);
@@ -809,7 +809,15 @@ READ8_MEMBER( pit8253_device::read )
 
 				case 3:
 					/* read bits 0-7 first, then 8-15 */
-					data = (value >> (timer->rmsb ? 8 : 0)) & 0xff;
+
+					// reading back the current count while in the middle of a
+					// 16-bit write returns a xor'ed version of the value written
+					// (apricot diagnostic timer test tests this)
+					if (timer->wmsb)
+						data = ~timer->lowcount;
+					else
+						data = value >> (timer->rmsb ? 8 : 0);
+
 					timer->rmsb = 1 - timer->rmsb;
 					break;
 				}
diff --git a/src/devices/machine/scnxx562.cpp b/src/devices/machine/scnxx562.cpp
index 7dfdfdc..87655ee 100644
--- a/src/devices/machine/scnxx562.cpp
+++ b/src/devices/machine/scnxx562.cpp
@@ -2544,13 +2544,13 @@ void duscc_channel::update_serial()
 
 	if (m_brg_rx_rate != 0)
 	{
-		if (m_brg_rx_rate == 1) m_brg_rx_rate = 0; // BRG beeing disabled
+		if (m_brg_rx_rate == 1) m_brg_rx_rate = 0; // BRG being disabled
 		set_rcv_rate(m_brg_rx_rate);
 		LOG(("   - Baud Rate Generator: %d mode: RX:%dx\n", m_brg_rx_rate, get_rx_clock_mode()));
 	}
 	if (m_brg_tx_rate != 0)
 	{
-		if (m_brg_tx_rate == 1) m_brg_tx_rate = 0; // BRG beeing disabled
+		if (m_brg_tx_rate == 1) m_brg_tx_rate = 0; // BRG being disabled
 		set_tra_rate(m_brg_tx_rate);
 		LOG(("   - Baud Rate Generator: %d mode: TX:%dx\n", m_brg_tx_rate, get_tx_clock_mode()));
 	}
diff --git a/src/devices/machine/upd765.cpp b/src/devices/machine/upd765.cpp
index fef20a7..b736b17 100644
--- a/src/devices/machine/upd765.cpp
+++ b/src/devices/machine/upd765.cpp
@@ -2070,7 +2070,7 @@ void upd765_family_device::format_track_continue(floppy_info &fi)
 			result[3] = 0;
 			result[4] = 0;
 			result[5] = 0;
-			result[6] = 0;
+			result[6] = command[2];
 			result_pos = 7;
 			command_end(fi, true);
 			return;
diff --git a/src/devices/machine/wd_fdc.cpp b/src/devices/machine/wd_fdc.cpp
index 5ae5554..a8e49bd 100644
--- a/src/devices/machine/wd_fdc.cpp
+++ b/src/devices/machine/wd_fdc.cpp
@@ -74,6 +74,7 @@ wd_fdc_t::wd_fdc_t(const machine_config &mconfig, device_type type, const char *
 	enmf_cb(*this)
 {
 	force_ready = false;
+	disable_motor_control = false;
 }
 
 void wd_fdc_t::set_force_ready(bool _force_ready)
@@ -81,6 +82,11 @@ void wd_fdc_t::set_force_ready(bool _force_ready)
 	force_ready = _force_ready;
 }
 
+void wd_fdc_t::set_disable_motor_control(bool _disable_motor_control)
+{
+	disable_motor_control = _disable_motor_control;
+}
+
 void wd_fdc_t::device_start()
 {
 	intrq_cb.resolve();
@@ -177,7 +183,7 @@ void wd_fdc_t::set_floppy(floppy_image_device *_floppy)
 	int next_ready = floppy ? floppy->ready_r() : 1;
 
 	if(floppy) {
-		if(motor_control)
+		if(motor_control && !disable_motor_control)
 			floppy->mon_w(status & S_MON ? 0 : 1);
 		floppy->setup_index_pulse_cb(floppy_image_device::index_pulse_cb(&wd_fdc_t::index_callback, this));
 		floppy->setup_ready_cb(floppy_image_device::ready_cb(&wd_fdc_t::ready_callback, this));
@@ -1243,7 +1249,7 @@ void wd_fdc_t::spinup()
 	}
 
 	status |= S_MON|S_SPIN;
-	if(floppy)
+	if(floppy && !disable_motor_control)
 		floppy->mon_w(0);
 }
 
@@ -1279,7 +1285,7 @@ void wd_fdc_t::index_callback(floppy_image_device *floppy, int state)
 			motor_timeout ++;
 			if(motor_control && motor_timeout >= 5) {
 				status &= ~S_MON;
-				if(floppy)
+				if(floppy && !disable_motor_control)
 					floppy->mon_w(1);
 			}
 
diff --git a/src/devices/machine/wd_fdc.h b/src/devices/machine/wd_fdc.h
index 9d792f3..ed82255 100644
--- a/src/devices/machine/wd_fdc.h
+++ b/src/devices/machine/wd_fdc.h
@@ -116,6 +116,9 @@
 #define MCFG_WD_FDC_FORCE_READY \
 	downcast<wd_fdc_t *>(device)->set_force_ready(true);
 
+#define MCFG_WD_FDC_DISABLE_MOTOR_CONTROL \
+	downcast<wd_fdc_t *>(device)->set_disable_motor_control(true);
+
 #define MCFG_WD_FDC_INTRQ_CALLBACK(_write) \
 	devcb = &wd_fdc_t::set_intrq_wr_callback(*device, DEVCB_##_write);
 
@@ -146,6 +149,7 @@ public:
 	void dden_w(bool dden);
 	void set_floppy(floppy_image_device *floppy);
 	void set_force_ready(bool force_ready);
+	void set_disable_motor_control(bool _disable_motor_control);
 
 	void cmd_w(uint8_t val);
 	uint8_t status_r();
@@ -369,7 +373,7 @@ private:
 
 	emu_timer *t_gen, *t_cmd, *t_track, *t_sector;
 
-	bool dden, status_type_1, intrq, drq, hld, hlt, enp, force_ready;
+	bool dden, status_type_1, intrq, drq, hld, hlt, enp, force_ready, disable_motor_control;
 	int main_state, sub_state;
 	uint8_t command, track, sector, data, status, intrq_cond;
 	int last_dir;
diff --git a/src/devices/machine/z80dart.cpp b/src/devices/machine/z80dart.cpp
index 4a3db5c..a5ff95a 100644
--- a/src/devices/machine/z80dart.cpp
+++ b/src/devices/machine/z80dart.cpp
@@ -814,6 +814,7 @@ uint8_t z80dart_channel::control_read()
 void z80dart_channel::control_write(uint8_t data)
 {
 	int reg = m_wr[0] & WR0_REGISTER_MASK;
+	uint8_t prev = m_wr[reg];
 
 	LOG(("Z80DART \"%s\" Channel %c : Control Register Write '%02x'\n", m_owner->tag(), 'A' + m_index, data));
 
@@ -882,6 +883,16 @@ void z80dart_channel::control_write(uint8_t data)
 			// return from interrupt
 			LOG(("Z80DART \"%s\" Channel %c : Return from Interrupt\n", m_owner->tag(), 'A' + m_index));
 			m_uart->z80daisy_irq_reti();
+			if((m_uart->m_variant == z80dart_device::TYPE_I8274) || (m_uart->m_variant == z80dart_device::TYPE_UPD7201))
+			{
+				if (m_uart->m_chanB->m_wr[1] & z80dart_channel::WR1_STATUS_VECTOR)
+				{
+					if((m_uart->m_chanA->m_wr[1] & 0x18) == z80dart_channel::WR2_MODE_8086_8088)
+						m_uart->m_chanB->m_rr[2] = (m_uart->m_chanB->m_wr[2] & 0xf8) | 0x07;
+					else
+						m_uart->m_chanB->m_rr[2] = (m_uart->m_chanB->m_wr[2] & 0xe3) | 0x1c;
+				}
+			}
 			break;
 		}
 		break;
@@ -934,7 +945,8 @@ void z80dart_channel::control_write(uint8_t data)
 		LOG(("Z80DART \"%s\" Channel %c : Auto Enables %u\n", m_owner->tag(), 'A' + m_index, (data & WR3_AUTO_ENABLES) ? 1 : 0));
 		LOG(("Z80DART \"%s\" Channel %c : Receiver Bits/Character %u\n", m_owner->tag(), 'A' + m_index, get_rx_word_length()));
 
-		update_serial();
+		if (data != prev)
+			update_serial();
 		break;
 
 	case 4:
@@ -943,7 +955,8 @@ void z80dart_channel::control_write(uint8_t data)
 		LOG(("Z80DART \"%s\" Channel %c : Stop Bits %s\n", m_owner->tag(), 'A' + m_index, stop_bits_tostring(get_stop_bits())));
 		LOG(("Z80DART \"%s\" Channel %c : Clock Mode %uX\n", m_owner->tag(), 'A' + m_index, get_clock_mode()));
 
-		update_serial();
+		if (data != prev)
+			update_serial();
 		break;
 
 	case 5:
@@ -953,7 +966,8 @@ void z80dart_channel::control_write(uint8_t data)
 		LOG(("Z80DART \"%s\" Channel %c : Request to Send %u\n", m_owner->tag(), 'A' + m_index, (data & WR5_RTS) ? 1 : 0));
 		LOG(("Z80DART \"%s\" Channel %c : Data Terminal Ready %u\n", m_owner->tag(), 'A' + m_index, (data & WR5_DTR) ? 1 : 0));
 
-		update_serial();
+		if (data != prev)
+			update_serial();
 
 		if (data & WR5_RTS)
 		{
diff --git a/src/devices/machine/z80scc.cpp b/src/devices/machine/z80scc.cpp
index c531c6b..b6616f4 100644
--- a/src/devices/machine/z80scc.cpp
+++ b/src/devices/machine/z80scc.cpp
@@ -79,16 +79,17 @@ DONE (x) (p=partly)         NMOS         CMOS       ESCC      EMSCC
 // printf("TAG %lld %s%s Data:%d\n", machine().firstcpu->total_cycles(), __PRETTY_FUNCTION__, m_owner->tag(), data);
 
 #define VERBOSE 0
-#define LOGPRINT(x) do { if (VERBOSE) logerror x; } while (0)
-#define LOG(x)      {} LOGPRINT(x)
-#define LOGR(x)     {} LOGPRINT(x)
-#define LOGSETUP(x) {} LOGPRINT(x)
-#define LOGINT(x)   {} LOGPRINT(x)
-#define LOGTX(x)    {} LOGPRINT(x)
-#define LOGRCV(x)   {} LOGPRINT(x)
-#define LOGCTS(x)   {} LOGPRINT(x)
-#define LOGDCD(x)   {} LOGPRINT(x)
-#define LOGSYNC(x)  {} LOGPRINT(x)
+#define LOGPRINT(...)   do { if (VERBOSE) logerror(__VA_ARGS__); } while (0)
+#define LOG(...)        {} LOGPRINT(__VA_ARGS__)
+#define LOGR(...)       {}
+#define LOGSETUP(...)   {} LOGPRINT(__VA_ARGS__)
+#define LOGINT(...)     {}
+#define LOGCMD(...)     {}
+#define LOGTX(...)      {}
+#define LOGRCV(...)     {}
+#define LOGCTS(...)     {}
+#define LOGDCD(...)     {}
+#define LOGSYNC(...)    {}
 #if VERBOSE == 2
 #define logerror printf
 #endif
@@ -235,7 +236,7 @@ scc8523L_device::scc8523L_device(const machine_config &mconfig, const char *tag,
 
 void z80scc_device::device_start()
 {
-	LOGSETUP(("%s\n", FUNCNAME));
+	LOGSETUP("%s\n", FUNCNAME);
 	// resolve callbacks
 	m_out_txda_cb.resolve_safe();
 	m_out_dtra_cb.resolve_safe();
@@ -258,7 +259,7 @@ void z80scc_device::device_start()
 	save_item(NAME(m_int_source));
 	save_item(NAME(m_wr9));
 	save_item(NAME(m_wr0_ptrbits));
-	LOG((" - SCC variant %02x\n", m_variant));
+	LOG(" - SCC variant %02x\n", m_variant);
 }
 
 
@@ -268,7 +269,7 @@ void z80scc_device::device_start()
 
 void z80scc_device::device_reset()
 {
-	LOGSETUP(("%s %s \n",tag(), FUNCNAME));
+	LOGSETUP("%s %s \n",tag(), FUNCNAME);
 
 	// Do channel reset on both channels
 	m_chanA->reset();
@@ -332,9 +333,9 @@ int z80scc_device::z80daisy_irq_state()
 {
 	int state = 0;
 
-	LOGINT(("%s %s A:%d%d%d B:%d%d%d ",tag(), FUNCNAME,
+	LOGINT("%s %s A:%d%d%d B:%d%d%d ", tag(), FUNCNAME,
 			m_int_state[0], m_int_state[1], m_int_state[2],
-			m_int_state[3], m_int_state[4], m_int_state[5]));
+			m_int_state[3], m_int_state[4], m_int_state[5]);
 
 	// loop over all interrupt sources
 	for (auto & elem : m_int_state)
@@ -351,7 +352,7 @@ int z80scc_device::z80daisy_irq_state()
 	// Last chance to keep the control of the interrupt line
 	state |= (m_wr9 & z80scc_channel::WR9_BIT_DLC) ? Z80_DAISY_IEO : 0;
 
-	LOGINT(("- Interrupt State %u\n", state));
+	LOGINT("- Interrupt State %u\n", state);
 
 	return state;
 }
@@ -362,7 +363,7 @@ int z80scc_device::z80daisy_irq_state()
 //-------------------------------------------------
 int z80scc_device::z80daisy_irq_ack()
 {
-	LOGINT(("%s %s \n",tag(), FUNCNAME));
+	LOGINT("%s %s \n",tag(), FUNCNAME);
 	// loop over all interrupt sources
 	for (auto & elem : m_int_state)
 	{
@@ -371,15 +372,15 @@ int z80scc_device::z80daisy_irq_ack()
 		{
 			elem = Z80_DAISY_IEO; // Set IUS bit (called IEO in z80 daisy lingo)
 			check_interrupts();
-			LOGINT((" - Found an INT request, "));
+			LOGINT(" - Found an INT request, ");
 			if (m_wr9 & z80scc_channel::WR9_BIT_VIS)
 			{
-				LOGINT(("but WR9 D1 set to use autovector, returning -1\n"));
+				LOGINT("but WR9 D1 set to use autovector, returning -1\n");
 				return -1;
 			}
 			else
 			{
-				LOGINT(("returning RR2: %02x\n", m_chanB->m_rr2 ));
+				LOGINT("returning RR2: %02x\n", m_chanB->m_rr2 );
 				return m_chanB->m_rr2;
 			}
 		}
@@ -401,7 +402,7 @@ daisy chain, the SCC has a Disable Lower Chain (DLC) software command (WR9 bit 2
 */
 void z80scc_device::z80daisy_irq_reti()
 {
-	LOGINT(("%s %s - No RETI detection needed on SCC\n",tag(), FUNCNAME));
+	LOGINT("%s %s - No RETI detection needed on SCC\n",tag(), FUNCNAME);
 }
 
 
@@ -412,7 +413,7 @@ void z80scc_device::z80daisy_irq_reti()
 void z80scc_device::check_interrupts()
 {
 	int state = (z80daisy_irq_state() & Z80_DAISY_INT) ? ASSERT_LINE : CLEAR_LINE;
-	LOGINT(("%s %s \n",tag(), FUNCNAME));
+	LOGINT("%s %s \n",tag(), FUNCNAME);
 	m_out_int_cb(state);
 }
 
@@ -423,7 +424,7 @@ void z80scc_device::check_interrupts()
 
 void z80scc_device::reset_interrupts()
 {
-	LOGINT(("%s %s \n",tag(), FUNCNAME));
+	LOGINT("%s %s \n",tag(), FUNCNAME);
 	// reset internal interrupt sources
 	for (auto & elem : m_int_state)
 	{
@@ -478,7 +479,7 @@ int z80scc_device::get_extint_priority(int type)
 	case z80scc_channel::INT_EXTERNAL: prio = z80scc_channel::INT_EXTERNAL_PRIO; break;
 	case z80scc_channel::INT_TRANSMIT: prio = z80scc_channel::INT_TRANSMIT_PRIO; break;
 	case z80scc_channel::INT_SPECIAL:  prio = z80scc_channel::INT_SPECIAL_PRIO;  break;
-	default: logerror("Bad interrupt source beeing prioritized!");
+	default: logerror("Bad interrupt source being prioritized!");
 	}
 	return prio;
 }
@@ -494,12 +495,12 @@ void z80scc_device::trigger_interrupt(int index, int type)
 
 	int prio_level = 0;
 
-	LOGINT(("%s %s:%c %02x \n",FUNCNAME, tag(), 'A' + index, type));
+	LOGINT("%s %s:%c %02x \n",FUNCNAME, tag(), 'A' + index, type);
 
 	/* The Master Interrupt Enable (MIE) bit, WR9 D3, must be set to enable the SCC to generate interrupts.*/
 	if (!(m_wr9 & z80scc_channel::WR9_BIT_MIE))
 	{
-		LOGINT(("Master Interrupt Enable is not set, blocking attempt to interrupt\n"));
+		LOGINT("Master Interrupt Enable is not set, blocking attempt to interrupt\n");
 		return;
 	}
 
@@ -516,7 +517,7 @@ void z80scc_device::trigger_interrupt(int index, int type)
 		vector = modify_vector(vector, index, source);
 	}
 
-	LOGINT(("   Interrupt Request fired of type %u and vector %02x\n", type, vector));
+	LOGINT("   Interrupt Request fired of type %u and vector %02x\n", type, vector);
 
 	// update vector register
 	m_chanB->m_rr2 = vector;
@@ -553,11 +554,11 @@ int z80scc_device::update_extint(int index)
 	uint8_t wr15 = (index == CHANNEL_A ? m_chanA->m_wr15 : m_chanB->m_wr15);
 	uint8_t lrr0 = (index == CHANNEL_A ? m_chanA->m_extint_states : m_chanB->m_extint_states);
 
-	LOGINT(("%s(%02x)\n", FUNCNAME, index));
+	LOGINT("%s(%02x)\n", FUNCNAME, index);
 	// Check if any of the enabled external interrupt sources has changed and requiresd service TODO: figure out Zero Count
 	if ( ((lrr0 & wr15 & 0xf8) ^ (rr0 & wr15 & 0xf8)) == 0 ) // mask off disabled and non relevant bits
 	{
-		LOGINT((" - All interrupts serviced\n"));
+		LOGINT(" - All interrupts serviced\n");
 
 		// Reset IP bit for external interrupts in both internal structure and rr3
 		// - External and Special interripts has the same prio, just add channel offset
@@ -568,7 +569,7 @@ int z80scc_device::update_extint(int index)
 	}
 	else
 	{
-		LOGINT((" - More external/status interrupts to serve: %02x\n", ((lrr0 & wr15 & 0xf8) ^ (rr0 & wr15 & 0xf8))));
+		LOGINT(" - More external/status interrupts to serve: %02x\n", ((lrr0 & wr15 & 0xf8) ^ (rr0 & wr15 & 0xf8)));
 	}
 	return ret;
 }
@@ -605,7 +606,7 @@ READ8_MEMBER( z80scc_device::zbus_r )
 	case z80scc_channel::WR0_Z_SEL_SHFT_RIGHT: ba = offset & 0x10; reg = (offset >> 1) & 0x0f; break; /* Shift Right mode */
 	default:
 		logerror("Malformed Z-bus SCC read: offset %02x WR0 bits %02x\n", offset, m_chanB->m_wr0);
-		LOG(("Malformed Z-bus SCC read: offset %02x WR0 bits %02x\n", offset, m_chanB->m_wr0));
+		LOG("Malformed Z-bus SCC read: offset %02x WR0 bits %02x\n", offset, m_chanB->m_wr0);
 		return data;
 	}
 
@@ -638,7 +639,7 @@ WRITE8_MEMBER( z80scc_device::zbus_w )
 	case z80scc_channel::WR0_Z_SEL_SHFT_RIGHT: ba = offset & 0x10; reg = (offset >> 1) & 0x0f; break; /* Shift Right mode */
 	default:
 		logerror("Malformed Z-bus SCC write: offset %02x WR0 bits %02x\n", offset, m_chanB->m_wr0);
-		LOG(("Malformed Z-bus SCC write: offset %02x WR0 bits %02x\n", offset, m_chanB->m_wr0));
+		LOG("Malformed Z-bus SCC write: offset %02x WR0 bits %02x\n", offset, m_chanB->m_wr0);
 	}
 
 	if (ba == 0)
@@ -665,7 +666,7 @@ READ8_MEMBER( z80scc_device::cd_ab_r )
 		return 0;
 	}
 
-	//    LOG(("z80scc_device::cd_ba_r ba:%02x cd:%02x\n", ba, cd));
+	//    LOG("z80scc_device::cd_ba_r ba:%02x cd:%02x\n", ba, cd);
 	return cd ? channel->data_read() : channel->control_read();
 }
 
@@ -685,7 +686,7 @@ WRITE8_MEMBER( z80scc_device::cd_ab_w )
 		return;
 	}
 
-	LOG((" cd_ab_w %02x => ba:%02x cd:%02x (ofs %d)\n", data, ba, cd, offset&3));
+	LOG(" cd_ab_w %02x => ba:%02x cd:%02x (ofs %d)\n", data, ba, cd, offset&3);
 	if (cd)
 		channel->data_write(data);
 	else
@@ -708,7 +709,7 @@ READ8_MEMBER( z80scc_device::cd_ba_r )
 		return 0;
 	}
 
-	//    LOG(("z80scc_device::cd_ba_r ba:%02x cd:%02x\n", ba, cd));
+	//    LOG("z80scc_device::cd_ba_r ba:%02x cd:%02x\n", ba, cd);
 	return cd ? channel->control_read() : channel->data_read();
 }
 
@@ -728,7 +729,7 @@ WRITE8_MEMBER( z80scc_device::cd_ba_w )
 		return;
 	}
 
-	//    LOG(("z80scc_device::cd_ba_w ba:%02x cd:%02x\n", ba, cd));
+	//    LOG("z80scc_device::cd_ba_w ba:%02x cd:%02x\n", ba, cd);
 	if (cd)
 		channel->control_write(data);
 	else
@@ -753,7 +754,7 @@ READ8_MEMBER( z80scc_device::ba_cd_r )
 		return 0;
 	}
 
-	//    LOG(("z80scc_device::ba_cd_r ba:%02x cd:%02x\n", ba, cd));
+	//    LOG("z80scc_device::ba_cd_r ba:%02x cd:%02x\n", ba, cd);
 	return cd ? channel->control_read() : channel->data_read();
 }
 
@@ -775,7 +776,7 @@ WRITE8_MEMBER( z80scc_device::ba_cd_w )
 		return;
 	}
 
-	LOG(("z80scc_device::ba_cd_w ba:%02x cd:%02x\n", ba, cd));
+	LOG("z80scc_device::ba_cd_w ba:%02x cd:%02x\n", ba, cd);
 
 	if (cd)
 		channel->control_write(data);
@@ -800,7 +801,7 @@ READ8_MEMBER( z80scc_device::ba_cd_inv_r )
 		return 0;
 	}
 
-	//    LOG(("z80scc_device::ba_cd_inv_r ba:%02x cd:%02x\n", ba, cd));
+	//    LOG("z80scc_device::ba_cd_inv_r ba:%02x cd:%02x\n", ba, cd);
 	return cd ? channel->data_read() : channel->control_read();
 }
 
@@ -822,7 +823,7 @@ WRITE8_MEMBER( z80scc_device::ba_cd_inv_w )
 		return;
 	}
 
-	LOG(("z80scc_device::ba_cd_inv_w ba:%02x cd:%02x\n", ba, cd));
+	LOG("z80scc_device::ba_cd_inv_w ba:%02x cd:%02x\n", ba, cd);
 
 	if (cd)
 		channel->data_write(data);
@@ -862,7 +863,7 @@ z80scc_channel::z80scc_channel(const machine_config &mconfig, const char *tag, d
 		,m_rcv_mode(RCV_IDLE)
 #endif
 {
-	LOG(("%s\n",FUNCNAME));
+	LOG("%s\n",FUNCNAME);
 
 	// Reset all registers
 	m_rr0 = m_rr1 = m_rr2 = m_rr3  = m_rr4  = m_rr5  = m_rr6  = m_rr7 = m_rr7p = m_rr8
@@ -887,7 +888,7 @@ z80scc_channel::z80scc_channel(const machine_config &mconfig, const char *tag, d
 
 void z80scc_channel::device_start()
 {
-	LOGSETUP(("%s\n", FUNCNAME));
+	LOGSETUP("%s\n", FUNCNAME);
 	m_uart = downcast<z80scc_device *>(owner());
 	m_index = m_uart->get_channel_index(this);
 
@@ -969,7 +970,7 @@ void z80scc_channel::device_start()
 
 void z80scc_channel::device_reset()
 {
-	LOGSETUP(("%s\n", FUNCNAME));
+	LOGSETUP("%s\n", FUNCNAME);
 
 	// Reset RS232 emulation
 	receive_register_reset();
@@ -1012,7 +1013,7 @@ void z80scc_channel::device_reset()
 
 void z80scc_channel::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
 {
-//  LOG(("%s %d\n", FUNCNAME, id));
+//  LOG("%s %d\n", FUNCNAME, id);
 
 #if LOCAL_BRG
 	switch(id)
@@ -1031,7 +1032,7 @@ void z80scc_channel::device_timer(emu_timer &timer, device_timer_id id, int para
 			}
 			else
 			{
-				LOG((" - turning off Baudrate timer\n"));
+				LOG(" - turning off Baudrate timer\n");
 				timer.adjust(attotime::never, 0, attotime::never);
 			}
 		}
@@ -1055,7 +1056,7 @@ void z80scc_channel::tra_callback()
 {
 	if (!(m_wr5 & WR5_TX_ENABLE))
 	{
-		LOG((LLFORMAT " %s() \"%s \"Channel %c transmit mark 1 m_wr5:%02x\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, m_wr5));
+		LOG(LLFORMAT " %s() \"%s \"Channel %c transmit mark 1 m_wr5:%02x\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, m_wr5);
 		// transmit mark
 		if (m_index == z80scc_device::CHANNEL_A)
 			m_uart->m_out_txda_cb(1);
@@ -1064,7 +1065,7 @@ void z80scc_channel::tra_callback()
 	}
 	else if (m_wr5 & WR5_SEND_BREAK)
 	{
-		LOG((LLFORMAT " %s() \"%s \"Channel %c send break 1 m_wr5:%02x\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, m_wr5));
+		LOG(LLFORMAT " %s() \"%s \"Channel %c send break 1 m_wr5:%02x\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, m_wr5);
 		// transmit break
 		if (m_index == z80scc_device::CHANNEL_A)
 			m_uart->m_out_txda_cb(0);
@@ -1075,7 +1076,7 @@ void z80scc_channel::tra_callback()
 	{
 		int db = transmit_register_get_data_bit();
 
-		LOG((LLFORMAT " %s() \"%s \"Channel %c transmit data bit %d m_wr5:%02x\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, db, m_wr5));
+		LOG(LLFORMAT " %s() \"%s \"Channel %c transmit data bit %d m_wr5:%02x\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, db, m_wr5);
 		// transmit data
 		if (m_index == z80scc_device::CHANNEL_A)
 			m_uart->m_out_txda_cb(db);
@@ -1084,7 +1085,7 @@ void z80scc_channel::tra_callback()
 	}
 	else
 	{
-		LOG((LLFORMAT " %s() \"%s \"Channel %c Failed to transmit m_wr5:%02x\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, m_wr5));
+		LOG(LLFORMAT " %s() \"%s \"Channel %c Failed to transmit m_wr5:%02x\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, m_wr5);
 		logerror("%s \"%s \"Channel %c Failed to transmit\n", FUNCNAME, m_owner->tag(), 'A' + m_index);
 	}
 }
@@ -1101,7 +1102,7 @@ void z80scc_channel::tra_complete()
 	{
 		m_delayed_tx_brg_change = 0;
 		set_tra_rate(m_brg_rate);
-		LOG(("Delayed Init - Baud Rate Generator: %d mode: %dx\n", m_brg_rate, get_clock_mode() ));
+		LOG("Delayed Init - Baud Rate Generator: %d mode: %dx\n", m_brg_rate, get_clock_mode() );
 	}
 
 	if ((m_wr5 & WR5_TX_ENABLE) && !(m_wr5 & WR5_SEND_BREAK))
@@ -1109,15 +1110,15 @@ void z80scc_channel::tra_complete()
 		if ( (m_rr0 & RR0_TX_BUFFER_EMPTY) == 0 || // Takes care of the NMOS/CMOS 1 slot TX FIFO
 			 m_tx_fifo_rp != m_tx_fifo_wp) // or there are more characters to send in a longer FIFO.
 		{
-			LOGTX((" %s() %s %c done sending, loading data from fifo:%02x '%c'\n", FUNCNAME, m_owner->tag(), 'A' + m_index,
-				   m_tx_data_fifo[m_tx_fifo_rp], isascii(m_tx_data_fifo[m_tx_fifo_rp]) ? m_tx_data_fifo[m_tx_fifo_rp] : ' '));
+			LOGTX(" %s() %s %c done sending, loading data from fifo:%02x '%c'\n", FUNCNAME, m_owner->tag(), 'A' + m_index,
+				   m_tx_data_fifo[m_tx_fifo_rp], isascii(m_tx_data_fifo[m_tx_fifo_rp]) ? m_tx_data_fifo[m_tx_fifo_rp] : ' ');
 			transmit_register_setup(m_tx_data_fifo[m_tx_fifo_rp]); // Reload the shift register
 			m_tx_fifo_rp_step();
 			m_rr0 |= RR0_TX_BUFFER_EMPTY; // Now here is room in the tx fifo again
 		}
 		else
 		{
-			LOGTX((" %s() %s %c done sending, setting all sent bit\n", FUNCNAME, m_owner->tag(), 'A' + m_index));
+			LOGTX(" %s() %s %c done sending, setting all sent bit\n", FUNCNAME, m_owner->tag(), 'A' + m_index);
 			m_rr1 |= RR1_ALL_SENT;
 
 			// when the RTS bit is reset, the _RTS output goes high after the transmitter empties
@@ -1141,7 +1142,7 @@ void z80scc_channel::tra_complete()
 	}
 	else if (m_wr5 & WR5_SEND_BREAK)
 	{
-		LOG((LLFORMAT " %s() \"%s \"Channel %c Transmit Break 0 m_wr5:%02x\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, m_wr5));
+		LOG(LLFORMAT " %s() \"%s \"Channel %c Transmit Break 0 m_wr5:%02x\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, m_wr5);
 		// transmit break
 		if (m_index == z80scc_device::CHANNEL_A)
 			m_uart->m_out_txda_cb(0);
@@ -1150,7 +1151,7 @@ void z80scc_channel::tra_complete()
 	}
 	else
 	{
-		LOG((LLFORMAT " %s() \"%s \"Channel %c Transmit Mark 1 m_wr5:%02x\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, m_wr5));
+		LOG(LLFORMAT " %s() \"%s \"Channel %c Transmit Mark 1 m_wr5:%02x\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, m_wr5);
 		// transmit mark
 		if (m_index == z80scc_device::CHANNEL_A)
 			m_uart->m_out_txda_cb(1);
@@ -1168,13 +1169,13 @@ void z80scc_channel::rcv_callback()
 {
 	if (m_wr3 & WR3_RX_ENABLE)
 	{
-		LOG((LLFORMAT " %s() \"%s \"Channel %c receive data bit %d m_wr3:%02x\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, m_rxd, m_wr3));
+		LOG(LLFORMAT " %s() \"%s \"Channel %c receive data bit %d m_wr3:%02x\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, m_rxd, m_wr3);
 		receive_register_update_bit(m_rxd);
 	}
 #if 1
 	else
 	{
-		LOG((LLFORMAT " %s() \"%s \"Channel %c Received Data Bit but receiver is disabled\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index));
+		LOG(LLFORMAT " %s() \"%s \"Channel %c Received Data Bit but receiver is disabled\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index);
 		logerror("%s \"%s \"Channel %c Received data dit but receiver is disabled\n", FUNCNAME, m_owner->tag(), 'A' + m_index);
 	}
 #endif
@@ -1191,7 +1192,7 @@ void z80scc_channel::rcv_complete()
 
 	receive_register_extract();
 	data = get_received_char();
-	LOG((LLFORMAT " %s() \"%s \"Channel %c Received Data %c\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, data));
+	LOG(LLFORMAT " %s() \"%s \"Channel %c Received Data %c\n", machine().firstcpu->total_cycles(), FUNCNAME, m_owner->tag(), 'A' + m_index, data);
 	receive_data(data);
 #if START_BIT_HUNT
 	m_rcv_mode = RCV_SEEKING;
@@ -1231,7 +1232,7 @@ TODO:
 */
 void z80scc_channel::set_rts(int state)
 {
-	LOG(("%s(%d) \"%s\": %c \n", FUNCNAME, state, m_owner->tag(), 'A' + m_index));
+	LOG("%s(%d) \"%s\": %c \n", FUNCNAME, state, m_owner->tag(), 'A' + m_index);
 	if (m_index == z80scc_device::CHANNEL_A)
 		m_uart->m_out_rtsa_cb(state);
 	else
@@ -1240,7 +1241,7 @@ void z80scc_channel::set_rts(int state)
 
 void z80scc_channel::update_rts()
 {
-//    LOG(("%s(%d) \"%s\": %c \n", FUNCNAME, state, m_owner->tag(), 'A' + m_index));
+//    LOG("%s(%d) \"%s\": %c \n", FUNCNAME, state, m_owner->tag(), 'A' + m_index);
 		if (m_wr5 & WR5_RTS)
 		{
 				// when the RTS bit is set, the _RTS output goes low
@@ -1321,16 +1322,16 @@ uint8_t z80scc_channel::do_sccreg_rr0()
 {
 	uint8_t rr0 = m_rr0;
 
-	LOGINT(("%s %c %s <- %02x\n",tag(), 'A' + m_index, FUNCNAME, m_rr0));
+	LOG("%s %c %s <- %02x\n",tag(), 'A' + m_index, FUNCNAME, m_rr0);
 	if (m_extint_latch == 1)
 	{
 		rr0 &=                     ((~m_wr15) | WR15_WR7PRIME | WR15_STATUS_FIFO);  // clear enabled bits, saving 2 unrelated bits
 		rr0 |= (m_extint_states & ~((~m_wr15) | WR15_WR7PRIME | WR15_STATUS_FIFO)); // set enabled bits to latched states
-		LOGINT(("- %c returning latched value RR0:%02x WR15:%02x => %02x\n", 'A' + m_index, m_rr0, m_wr15, rr0));
+		LOGINT("- %c returning latched value RR0:%02x WR15:%02x => %02x\n", 'A' + m_index, m_rr0, m_wr15, rr0);
 	}
 	else
 	{
-		LOGINT(("- %c returning unlatched value: %02x\n", 'A' + m_index, rr0));
+		LOG("- %c returning unlatched value: %02x\n", 'A' + m_index, rr0);
 	}
 
 	return rr0;
@@ -1341,7 +1342,7 @@ uint8_t z80scc_channel::do_sccreg_rr0()
  * codes for the I-Field in the SDLC Receive Mode. */
 uint8_t z80scc_channel::do_sccreg_rr1()
 {
-	LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, m_rr1));
+	LOGR("%s %s <- %02x\n",tag(), FUNCNAME, m_rr1);
 	return m_rr1;
 }
 
@@ -1353,7 +1354,7 @@ on the state of the Status High/Status Low bit in WR9 and independent of the sta
 in WR9."*/
 uint8_t z80scc_channel::do_sccreg_rr2()
 {
-	LOGINT(("%s\n", FUNCNAME));
+	LOGINT("%s\n", FUNCNAME);
 
 	// Assume the unmodified in polled mode
 	m_rr2 = m_uart->m_chanA->m_wr2;
@@ -1363,18 +1364,18 @@ uint8_t z80scc_channel::do_sccreg_rr2()
 	{
 		int i = 0;
 
-		LOGINT((" - Channel B so we might need to update the vector modification\n"));
+		LOGINT(" - Channel B so we might need to update the vector modification\n");
 		// loop over all interrupt sources
 		for (auto & elem : m_uart->m_int_state)
 		{
 			// find the first channel with an interrupt requested
 			if (elem & Z80_DAISY_INT)
 			{
-				LOGINT((" - Checking an INT source %d\n", i));
+				LOGINT(" - Checking an INT source %d\n", i);
 				m_rr2 = m_uart->modify_vector(m_rr2, i < 3 ? z80scc_device::CHANNEL_A : z80scc_device::CHANNEL_B, m_uart->m_int_source[i] & 3);
 				if ((m_uart->m_variant & (SET_ESCC | SET_CMOS)) && (m_uart->m_wr9 & WR9_BIT_IACK))
 				{
-					LOGINT((" - Found an INT request to ack while reading RR2\n"));
+					LOGINT(" - Found an INT request to ack while reading RR2\n");
 					elem = Z80_DAISY_IEO; // Set IUS bit (called IEO in z80 daisy lingo)
 					m_uart->check_interrupts();
 				}
@@ -1393,7 +1394,7 @@ B, all 0s are returned. The two unused bits are always returned as 0. Figure dis
 */
 uint8_t z80scc_channel::do_sccreg_rr3()
 {
-	LOGINT(("%s(%02x)\n", FUNCNAME, m_rr3));
+	LOGINT("%s(%02x)\n", FUNCNAME, m_rr3);
 	return m_rr3; // TODO Update all bits of this status register
 }
 
@@ -1404,7 +1405,7 @@ uint8_t z80scc_channel::do_sccreg_rr3()
   a read to this location returns an image of RR0.*/
 uint8_t z80scc_channel::do_sccreg_rr4()
 {
-	LOGR(("%s\n", FUNCNAME));
+	LOGR("%s\n", FUNCNAME);
 	if (m_uart->m_variant & (SET_ESCC | z80scc_device::TYPE_SCC85C30))
 		return (BIT(m_wr7, 6) ? m_wr4 : m_rr0);
 	else
@@ -1417,7 +1418,7 @@ uint8_t z80scc_channel::do_sccreg_rr4()
   a read to this register returns an image of RR1.*/
 uint8_t z80scc_channel::do_sccreg_rr5()
 {
-	LOGR(("%s\n", FUNCNAME));
+	LOGR("%s\n", FUNCNAME);
 	if (m_uart->m_variant & (SET_ESCC | z80scc_device::TYPE_SCC85C30))
 		return BIT(m_wr7, 6) ? m_wr5 : m_rr1;
 	else
@@ -1432,10 +1433,10 @@ uint8_t z80scc_channel::do_sccreg_rr5()
  On the NMOS version, a read to this register location returns an image of RR2.*/
 uint8_t z80scc_channel::do_sccreg_rr6()
 {
-	LOGR(("%s\n", FUNCNAME));
+	LOGR("%s\n", FUNCNAME);
 	if (m_wr15 & WR15_STATUS_FIFO)
 	{
-		LOGSYNC((" - Status FIFO for synchronous mode - not implemented\n"));
+		LOGSYNC(" - Status FIFO for synchronous mode - not implemented\n");
 		logerror(" - Status FIFO for synchronous mode - not implemented\n");
 		return 0;
 	}
@@ -1452,7 +1453,7 @@ uint8_t z80scc_channel::do_sccreg_rr6()
  RR7, RR6, RR1.*/
 uint8_t z80scc_channel::do_sccreg_rr7()
 {
-	LOGR(("%s\n", FUNCNAME));
+	LOGR("%s\n", FUNCNAME);
 	if (!(m_uart->m_variant & (SET_NMOS)))
 	{
 		logerror(" %s() not implemented feature\n", FUNCNAME);
@@ -1475,7 +1476,7 @@ uint8_t z80scc_channel::do_sccreg_rr8()
  of RR13. TODO: Check what is returned if Extended Read option is turned off */
 uint8_t z80scc_channel::do_sccreg_rr9()
 {
-	LOGR(("%s\n", FUNCNAME));
+	LOGR("%s\n", FUNCNAME);
 	if (m_uart->m_variant & (SET_ESCC | z80scc_device::TYPE_SCC85C30))
 		return BIT(m_wr7, 6) ? m_wr3 : m_rr13;
 	else
@@ -1485,7 +1486,7 @@ uint8_t z80scc_channel::do_sccreg_rr9()
 /* RR10 contains some SDLC related miscellaneous status bits. Unused bits are always 0. */
 uint8_t z80scc_channel::do_sccreg_rr10()
 {
-	LOGR(("%s\n", FUNCNAME));
+	LOGR("%s\n", FUNCNAME);
 	logerror("%s() not implemented feature\n", FUNCNAME);
 	return m_rr10;
 }
@@ -1496,7 +1497,7 @@ uint8_t z80scc_channel::do_sccreg_rr10()
  On the NMOS/CMOS version, a read to this location returns an image of RR15.*/
 uint8_t z80scc_channel::do_sccreg_rr11()
 {
-	LOGR(("%s\n", FUNCNAME));
+	LOGR("%s\n", FUNCNAME);
 	if (m_uart->m_variant & (SET_ESCC | z80scc_device::TYPE_SCC85C30))
 		return BIT(m_wr7, 6) ? m_wr10 : m_rr15;
 	else
@@ -1507,7 +1508,7 @@ uint8_t z80scc_channel::do_sccreg_rr11()
  RR12 returns the value stored in WR12, the lower byte of the time constant, for the BRG.*/
 uint8_t z80scc_channel::do_sccreg_rr12()
 {
-	LOGR(("%s\n", FUNCNAME));
+	LOGR("%s\n", FUNCNAME);
 	return m_wr12;
 }
 
@@ -1515,7 +1516,7 @@ uint8_t z80scc_channel::do_sccreg_rr12()
   RR13 returns the value stored in WR13, the upper byte of the time constant for the BRG. */
 uint8_t z80scc_channel::do_sccreg_rr13()
 {
-	LOGR(("%s\n", FUNCNAME));
+	LOGR("%s\n", FUNCNAME);
 	return m_wr13;
 }
 
@@ -1525,7 +1526,7 @@ Extended Read option has been enabled. Otherwise, this register returns an image
 On the NMOS/CMOS version, a read to this location returns an image of RR10.*/
 uint8_t z80scc_channel::do_sccreg_rr14()
 {
-	LOGR(("%s\n", FUNCNAME));
+	LOGR("%s\n", FUNCNAME);
 	if (m_uart->m_variant & (SET_ESCC | z80scc_device::TYPE_SCC85C30))
 		return BIT(m_wr7, 6) ? m_wr7 : m_rr10;
 	else
@@ -1537,7 +1538,7 @@ uint8_t z80scc_channel::do_sccreg_rr14()
  always returned as Os. */
 uint8_t z80scc_channel::do_sccreg_rr15()
 {
-	LOGR(("%s\n", FUNCNAME));
+	LOGR("%s\n", FUNCNAME);
 
 	return m_wr15 & 0xfa; // Mask out the used bits
 }
@@ -1548,7 +1549,7 @@ uint8_t z80scc_channel::do_sccreg_rr15()
 uint8_t z80scc_channel::scc_register_read( uint8_t reg)
 {
 	if (reg > 1)
-		LOG(("%s %02x\n", FUNCNAME, reg));
+		LOG("%s %02x\n", FUNCNAME, reg);
 	uint8_t data = 0;
 	uint8_t wreg = 0;
 
@@ -1610,46 +1611,22 @@ uint8_t z80scc_channel::control_read()
 	int reg = m_uart->m_wr0_ptrbits;
 	int regmask = (WR0_REGISTER_MASK | (m_uart->m_wr0_ptrbits & WR0_POINT_HIGH));
 
-	LOGR(("%s(%02x) reg %02x, regmask %02x, WR0 %02x\n", FUNCNAME, data, reg, regmask, m_wr0));
+	LOGR("%s(%02x) reg %02x, regmask %02x, WR0 %02x\n", FUNCNAME, data, reg, regmask, m_wr0);
 	m_uart->m_wr0_ptrbits = 0;
 	reg &= regmask;
 
 	if (reg != 0)
 	{
-		LOG(("%s(%02x) reg %02x, regmask %02x, WR0 %02x\n", FUNCNAME, data, reg, regmask, m_wr0));
+		LOG("%s(%02x) reg %02x, regmask %02x, WR0 %02x\n", FUNCNAME, data, reg, regmask, m_wr0);
 		m_wr0 &= ~regmask; // mask out register index
 	}
 
 	data = scc_register_read(reg);
 
-	//LOG(("%s \"%s\": %c : Register R%d read '%02x'\n", FUNCNAME, m_owner->tag(), 'A' + m_index, reg, data));
+	//LOG("%s \"%s\": %c : Register R%d read '%02x'\n", FUNCNAME, m_owner->tag(), 'A' + m_index, reg, data);
 	return data;
 }
 
-/* CRC Initialization Code handling - candidate for breaking out in a z80sio_base class
- Handle the WR0 CRC Reset/Init bits separatelly, needed by derived devices separatelly from the commands */
-void z80scc_channel::do_sccreg_wr0_resets(uint8_t data)
-{
-	LOG(("%s(%02x) %s",FUNCNAME, data, tag()));
-	switch (data & WR0_CRC_RESET_CODE_MASK)
-	{
-	case WR0_CRC_RESET_NULL:
-		LOG((" CRC_RESET_NULL\n"));
-		break;
-	case WR0_CRC_RESET_RX: /* In Synchronous mode: all Os (zeros) (CCITT-O CRC-16) */
-		LOGSYNC((" CRC_RESET_RX - not implemented\n"));
-		break;
-	case WR0_CRC_RESET_TX: /* In HDLC mode: all 1s (ones) (CCITT-1) */
-		LOGSYNC((" CRC_RESET_TX - not implemented\n"));
-		break;
-	case WR0_CRC_RESET_TX_UNDERRUN: /* Resets Tx underrun/EOM bit (D6 of the RRO register) */
-		LOGSYNC((" CRC_RESET_TX_UNDERRUN - not implemented\n"));
-		break;
-	default: /* Will not happen unless someone messes with the mask */
-		logerror(" Wrong CRC reset/init command:%02x\n", data & WR0_CRC_RESET_CODE_MASK);
-	}
-}
-
 /**/
 void z80scc_channel::do_sccreg_wr0(uint8_t data)
 {
@@ -1669,11 +1646,11 @@ void z80scc_channel::do_sccreg_wr0(uint8_t data)
 		  addressing*/
 		if (m_uart->m_variant & SET_Z85X3X)
 		{
-			LOG(("%s %s: %c : - Point High command\n", FUNCNAME, m_owner->tag(), 'A' + m_index));
+			LOG("%s %s: %c : - Point High command\n", FUNCNAME, m_owner->tag(), 'A' + m_index);
 			m_uart->m_wr0_ptrbits |= 8;
 		}
 		else
-			LOG(("%s %s: %c : - NULL command 2\n", FUNCNAME, m_owner->tag(), 'A' + m_index));
+			LOG("%s %s: %c : - NULL command 2\n", FUNCNAME, m_owner->tag(), 'A' + m_index);
 		break;
 	case WR0_RESET_EXT_STATUS:
 		/*After an External/Status interrupt (a change on a modem line or a break condition,
@@ -1688,8 +1665,8 @@ void z80scc_channel::do_sccreg_wr0(uint8_t data)
 		  (there are two transitions), another interrupt is not generated. Exceptions to this
 		  rule are detailed in the RR0 description.*/
 
-		LOGINT(("%s %s %c - Reset External/Status Interrupt, latch %s\n", m_owner->tag(), FUNCNAME, 'A' + m_index,
-			 m_extint_latch == 1? "is released" : "was already released"));
+		LOGCMD("%s %c - Reset External/Status Interrupt, latch %s\n", m_owner->tag(), 'A' + m_index,
+			 m_extint_latch == 1? "is released" : "was already released");
 		// Release latch if no other external or status sources are active
 		if ((m_extint_latch = m_uart->update_extint(m_index)) == 0)
 			m_uart->check_interrupts();
@@ -1702,18 +1679,18 @@ void z80scc_channel::do_sccreg_wr0(uint8_t data)
 		if (m_uart->m_variant & (SET_NMOS))
 		{
 			logerror("WR0 SWI ack command not supported on NMOS\n");
-			LOGINT(("\"%s\" %s: %c : Reset Highest IUS command not available on NMOS!\n", m_owner->tag(), FUNCNAME, 'A' + m_index));
+			LOGCMD("%s: %c : WR0_RESET_HIGHEST_IUS command not available on NMOS!\n", m_owner->tag(), 'A' + m_index);
 		}
 		else
 		{
-			LOGINT(("\"%s\" %s: %c : Reset Highest IUS\n", m_owner->tag(), FUNCNAME, 'A' + m_index));
+			LOGCMD("%s: %c : Reset Highest IUS\n", m_owner->tag(), 'A' + m_index);
 			// loop over all interrupt sources
 			for (auto & elem : m_uart->m_int_state)
 			{
 				// find the first channel with an interrupt requested
 				if (elem & Z80_DAISY_INT)
 				{
-					LOGINT(("- %c found IUS bit to clear\n", 'A' + m_index));
+					LOGCMD("- %c found IUS bit to clear\n", 'A' + m_index);
 					elem = 0; // Clear IUS bit (called IEO in z80 daisy lingo)
 					m_uart->check_interrupts();
 					break;
@@ -1727,30 +1704,44 @@ void z80scc_channel::do_sccreg_wr0(uint8_t data)
 		  data with the special condition is held in the Receive FIFO until this command is issued. If either
 		  of these modes is selected and this command is issued before the data has been read from the
 		  Receive FIFO, the data is lost */
-		LOG(("\"%s\" %s: %c : WR0_ERROR_RESET\n", m_owner->tag(), FUNCNAME, 'A' + m_index));
-		//do_sccreg_wr0(data); // reset status registers
+		LOGCMD("%s: %c : WR0_ERROR_RESET - not implemented\n", m_owner->tag(), 'A' + m_index);
 		m_rx_fifo_rp_step(); // Reset error state in fifo and unlock it. unlock == step to next slot in fifo.
 		break;
-	case WR0_SEND_ABORT:
-		data &= 0xef; // convert SCC SEND_ABORT command to a SIO SEND_ABORT command and fall through
-		/* The following commands relies on the SIO default behviour */
-	case WR0_NULL:
-		LOG(("\"%s\" Channel %c : Null\n", m_owner->tag(), 'A' + m_index));
+	case WR0_SEND_ABORT: // Flush transmitter and Send 8-13 bits of '1's, used with SDLC
+		LOGCMD("%s: %c : WR0_SEND_ABORT - not implemented\n", m_owner->tag(), 'A' + m_index);
 		break;
-	case WR0_ENABLE_INT_NEXT_RX:
-		// enable interrupt on next receive character
-		LOG(("\"%s\" Channel %c : Enable Interrupt on Next Received Character\n", m_owner->tag(), 'A' + m_index));
+	case WR0_NULL: // Do nothing
+		LOGCMD("%s: %c : WR0_NULL\n", m_owner->tag(), 'A' + m_index);
+		break;
+	case WR0_ENABLE_INT_NEXT_RX: // enable interrupt on next receive character
+		LOGCMD("%s: %c : WR0_ENABLE_INT_NEXT\n", m_owner->tag(), 'A' + m_index);
 		m_rx_first = 1;
 		break;
-	case WR0_RESET_TX_INT:
-		// reset transmitter interrupt pending
-		LOG(("\"%s\" Channel %c : Reset Transmitter Interrupt Pending\n", m_owner->tag(), 'A' + m_index));
-		logerror("\"%s\" Channel %c : unsupported command: Reset Transmitter Interrupt Pending\n", m_owner->tag(), 'A' + m_index);
+	case WR0_RESET_TX_INT: // reset transmitter interrupt pending
+		LOGCMD("%s: %c : WR0_RESET_TX_INT - not implemented\n", m_owner->tag(), 'A' + m_index);
 		break;
 	default:
 		break;
 	}
-	do_sccreg_wr0_resets(data);
+
+	/* CRC Initialization Code handling */
+	switch (data & WR0_CRC_RESET_CODE_MASK)
+	{
+	case WR0_CRC_RESET_NULL:
+		LOGCMD(" CRC_RESET_NULL\n");
+		break;
+	case WR0_CRC_RESET_RX: /* In Synchronous mode: all Os (zeros) (CCITT-O CRC-16) */
+		LOGCMD(" CRC_RESET_RX - not implemented\n");
+		break;
+	case WR0_CRC_RESET_TX: /* In HDLC mode: all 1s (ones) (CCITT-1) */
+		LOGCMD(" CRC_RESET_TX - not implemented\n");
+		break;
+	case WR0_CRC_RESET_TX_UNDERRUN: /* Resets Tx underrun/EOM bit (D6 of the RRO register) */
+		LOGCMD(" CRC_RESET_TX_UNDERRUN - not implemented\n");
+		break;
+	default: /* Will not happen unless someone messes with the mask */
+		logerror(" Wrong CRC reset/init command:%02x\n", data & WR0_CRC_RESET_CODE_MASK);
+	}
 
 	if ( m_uart->m_variant & SET_Z85X3X)
 	{
@@ -1762,36 +1753,38 @@ void z80scc_channel::do_sccreg_wr0(uint8_t data)
 /* Write Register 1 is the control register for the various SCC interrupt and Wait/Request modes.*/
 void z80scc_channel::do_sccreg_wr1(uint8_t data)
 {
-	LOG(("%s(%02x) \"%s\": %c : %s - %02x\n", FUNCNAME, data, m_owner->tag(), 'A' + m_index, FUNCNAME, data));
+	LOG("%s(%02x) \"%s\": %c : %s - %02x\n", FUNCNAME, data, m_owner->tag(), 'A' + m_index, FUNCNAME, data);
 	/* TODO: Sort out SCC specific behaviours  from legacy SIO behaviours:
 	   - Channel B only bits vs
 	   - Parity Is Special Condition, bit2 */
 	m_wr1 = data;
-	LOG(("- External Interrupt Enable %u\n", (data & WR1_EXT_INT_ENABLE) ? 1 : 0));
-	LOG(("- Transmit Interrupt Enable %u\n", (data & WR1_TX_INT_ENABLE) ? 1 : 0));
-	LOG(("- Parity is special condition %u\n", (data & WR1_PARITY_IS_SPEC_COND) ? 1 : 0));
-	LOG(("- Wait/Ready Enable %u\n", (data & WR1_WRDY_ENABLE) ? 1 : 0));
-	LOG(("- Wait/Ready Function %s\n", (data & WR1_WRDY_FUNCTION) ? "Ready" : "Wait"));
-	LOG(("- Wait/Ready on %s\n", (data & WR1_WRDY_ON_RX_TX) ? "Receive" : "Transmit"));
+	LOG("- External Interrupt Enable %u\n", (data & WR1_EXT_INT_ENABLE) ? 1 : 0);
+	LOG("- Transmit Interrupt Enable %u\n", (data & WR1_TX_INT_ENABLE) ? 1 : 0);
+	LOG("- Parity is special condition %u\n", (data & WR1_PARITY_IS_SPEC_COND) ? 1 : 0);
+	LOG("- Wait/Ready Enable %u\n", (data & WR1_WRDY_ENABLE) ? 1 : 0);
+	LOG("- Wait/Ready Function %s\n", (data & WR1_WRDY_FUNCTION) ? "Ready" : "Wait");
+	LOG("- Wait/Ready on %s\n", (data & WR1_WRDY_ON_RX_TX) ? "Receive" : "Transmit");
 
 	switch (data & WR1_RX_INT_MODE_MASK)
 	{
 	case WR1_RX_INT_DISABLE:
-		LOG(("- Receiver Interrupt Disabled\n"));
+		LOG("- Receiver Interrupt Disabled\n");
 		break;
 
 	case WR1_RX_INT_FIRST:
-		LOG(("- Receiver Interrupt on First Character\n"));
+		LOG("- Receiver Interrupt on First Character or Special Conditions\n");
 		break;
 
-	case WR1_RX_INT_ALL_PARITY:
-		LOG(("- Receiver Interrupt on All Characters, Parity Affects Vector\n"));
+	case WR1_RX_INT_ALL:
+		LOG("- Receiver Interrupt on All Characters or Special Conditions\n");
 		break;
 
-	case WR1_RX_INT_ALL:
-		LOG(("- Receiver Interrupt on All Characters\n"));
+	case WR1_RX_INT_PARITY:
+		LOG("- Receiver Interrupt on Special Conditions only\n");
 		break;
 	}
+	if ((data & WR1_RX_INT_MODE_MASK) == WR1_PARITY_IS_SPEC_COND)
+		LOG("- Parity error is a Special Condition\n");
 	m_uart->check_interrupts();
 }
 
@@ -1800,7 +1793,7 @@ void z80scc_channel::do_sccreg_wr1(uint8_t data)
    is controlled by the Vector Includes Status (VIS) and the Status High/Status Low bits in WR9.*/
 void z80scc_channel::do_sccreg_wr2(uint8_t data)
 {
-	LOG(("%s(%02x) Setting the interrupt vector\n", FUNCNAME, data));
+	LOG("%s(%02x) Setting the interrupt vector\n", FUNCNAME, data);
 	m_wr2 = data;
 	m_uart->m_chanA->m_rr2 = data;
 	m_uart->m_chanB->m_rr2 = data; /* TODO: Sort out the setting of ChanB depending on bits in WR9 */
@@ -1817,15 +1810,15 @@ void z80scc_channel::do_sccreg_wr2(uint8_t data)
   the Sync/Hunt bit is set again is by the Enter Hunt Mode command or by disabling the receiver.*/
 void z80scc_channel::do_sccreg_wr3(uint8_t data)
 {
-	LOG(("%s(%02x) Setting up the receiver\n", FUNCNAME, data));
+	LOG("%s(%02x) Setting up the receiver\n", FUNCNAME, data);
 	m_wr3 = data;
-	LOG(("- Receiver Enable:        %u\n", (data & WR3_RX_ENABLE) ? 1 : 0));
-	LOG(("- Sync Char Load Inhibit  %u\n", (data & WR3_SYNC_CHAR_LOAD_INHIBIT) ? 1 : 0));
-	LOG(("- Address Search Mode     %u\n", (data & WR3_ADDRESS_SEARCH_MODE) ? 1 : 0));
-	LOG(("- Rx CRC Enable           %u\n", (data & WR3_RX_CRC_ENABLE) ? 1 : 0));
-	LOG(("- Enter Hunt Mode         %u\n", (data & WR3_ENTER_HUNT_MODE) ? 1 : 0));
-	LOG(("- Auto Enables            %u\n", (data & WR3_AUTO_ENABLES) ? 1 : 0));
-	LOG(("- Receiver Bits/Character %u\n", get_rx_word_length()));
+	LOG("- Receiver Enable:        %u\n", (data & WR3_RX_ENABLE) ? 1 : 0);
+	LOG("- Sync Char Load Inhibit  %u\n", (data & WR3_SYNC_CHAR_LOAD_INHIBIT) ? 1 : 0);
+	LOG("- Address Search Mode     %u\n", (data & WR3_ADDRESS_SEARCH_MODE) ? 1 : 0);
+	LOG("- Rx CRC Enable           %u\n", (data & WR3_RX_CRC_ENABLE) ? 1 : 0);
+	LOG("- Enter Hunt Mode         %u\n", (data & WR3_ENTER_HUNT_MODE) ? 1 : 0);
+	LOG("- Auto Enables            %u\n", (data & WR3_AUTO_ENABLES) ? 1 : 0);
+	LOG("- Receiver Bits/Character %u\n", get_rx_word_length());
 
 	if ((m_wr3 & WR3_ENTER_HUNT_MODE) || ((m_wr3 & WR3_RX_ENABLE) == 0))
 	{
@@ -1837,7 +1830,7 @@ void z80scc_channel::do_sccreg_wr3(uint8_t data)
 
 void z80scc_channel::do_sccreg_wr4(uint8_t data)
 {
-	LOG(("%s(%02x) Setting up asynchronous frame format and clock\n", FUNCNAME, data));
+	LOG("%s(%02x) Setting up asynchronous frame format and clock\n", FUNCNAME, data);
 	if (data == m_wr4)
 	{
 		logerror("- suppressing reinit of Tx as write to wr4 is identical to previous value\n");
@@ -1845,14 +1838,14 @@ void z80scc_channel::do_sccreg_wr4(uint8_t data)
 	else
 	{
 		m_wr4 = data;
-		LOG(("- Parity    : %s\n", (data & WR4_PARITY_ENABLE) ? ((data & WR4_PARITY_EVEN) ? "Even" : "Odd") : "None"));
-		LOG(("- Stop Bits : %s\n", data & WR4_STOP_BITS_MASK ? stop_bits_tostring(get_stop_bits()) : "not used, sync modes enabled" ));
-		LOG(("- Sync Mode : %s\n", !(data & WR4_STOP_BITS_MASK) ?
+		LOG("- Parity    : %s\n", (data & WR4_PARITY_ENABLE) ? ((data & WR4_PARITY_EVEN) ? "Even" : "Odd") : "None");
+		LOG("- Stop Bits : %s\n", data & WR4_STOP_BITS_MASK ? stop_bits_tostring(get_stop_bits()) : "not used, sync modes enabled" );
+		LOG("- Sync Mode : %s\n", !(data & WR4_STOP_BITS_MASK) ?
 			 (data & WR4_BIT5 ?
 			  (data & WR4_BIT4 ? "External Sync Mode - /SYNC is used as input!" : "SDLC - not implemented")
 			  : (data & WR4_BIT4 ? "16 bit" : "8 bit"))
-			 : "Disabled"));
-		LOG(("- Clock Mode: %uX\n", get_clock_mode()));
+			 : "Disabled");
+		LOG("- Clock Mode: %uX\n", get_clock_mode());
 		update_serial();
 		safe_transmit_register_reset();
 		receive_register_reset();
@@ -1861,7 +1854,7 @@ void z80scc_channel::do_sccreg_wr4(uint8_t data)
 
 void z80scc_channel::do_sccreg_wr5(uint8_t data)
 {
-	LOG(("%s(%02x) Setting up the transmitter\n", FUNCNAME, data));
+	LOG("%s(%02x) Setting up the transmitter\n", FUNCNAME, data);
 	if (data == m_wr5)
 	{
 		logerror("- suppressing reinit of Tx as write to wr5 is identical to previous value\n");
@@ -1869,11 +1862,11 @@ void z80scc_channel::do_sccreg_wr5(uint8_t data)
 	else
 	{
 		m_wr5 = data;
-		LOG(("- Transmitter Enable %u\n", (data & WR5_TX_ENABLE) ? 1 : 0));
-		LOG(("- Transmitter Bits/Character %u\n", get_tx_word_length()));
-		LOG(("- Send Break %u\n", (data & WR5_SEND_BREAK) ? 1 : 0));
-		LOG(("- Request to Send %u\n", (data & WR5_RTS) ? 1 : 0));
-		LOG(("- Data Terminal Ready %u\n", (data & WR5_DTR) ? 1 : 0));
+		LOG("- Transmitter Enable %u\n", (data & WR5_TX_ENABLE) ? 1 : 0);
+		LOG("- Transmitter Bits/Character %u\n", get_tx_word_length());
+		LOG("- Send Break %u\n", (data & WR5_SEND_BREAK) ? 1 : 0);
+		LOG("- Request to Send %u\n", (data & WR5_RTS) ? 1 : 0);
+		LOG("- Data Terminal Ready %u\n", (data & WR5_DTR) ? 1 : 0);
 		update_serial();
 		safe_transmit_register_reset();
 		update_rts(); // Will also update DTR accordingly
@@ -1882,20 +1875,20 @@ void z80scc_channel::do_sccreg_wr5(uint8_t data)
 
 void z80scc_channel::do_sccreg_wr6(uint8_t data)
 {
-	LOG(("%s(%02x) Transmit sync\n", FUNCNAME, data));
+	LOG("%s(%02x) Transmit sync\n", FUNCNAME, data);
 	m_sync_pattern = (m_sync_pattern & 0xff00) | data;
 }
 
 void z80scc_channel::do_sccreg_wr7(uint8_t data)
 {
-	LOG(("%s(%02x) Receive sync\n", FUNCNAME, data));
+	LOG("%s(%02x) Receive sync\n", FUNCNAME, data);
 	m_sync_pattern = (data << 8) | (m_sync_pattern & 0xff);
 }
 
 /* WR8 is the transmit buffer register */
 void z80scc_channel::do_sccreg_wr8(uint8_t data)
 {
-	LOG(("%s(%02x) \"%s\": %c : Transmit Buffer write %02x\n", FUNCNAME, data, m_owner->tag(), 'A' + m_index, data));
+	LOG("%s(%02x) \"%s\": %c : Transmit Buffer write %02x\n", FUNCNAME, data, m_owner->tag(), 'A' + m_index, data);
 	data_write(data);
 }
 
@@ -1910,18 +1903,18 @@ void z80scc_channel::do_sccreg_wr9(uint8_t data)
 	switch (data & WR9_CMD_MASK)
 	{
 	case WR9_CMD_NORESET:
-		LOG(("\"%s\": %c : Master Interrupt Control - No reset  %02x\n", m_owner->tag(), 'A' + m_index, data));
+		LOG("\"%s\": %c : Master Interrupt Control - No reset  %02x\n", m_owner->tag(), 'A' + m_index, data);
 		break;
 	case WR9_CMD_CHNB_RESET:
-		LOGINT(("\"%s\": %c : Master Interrupt Control - Channel B reset  %02x\n", m_owner->tag(), 'A' + m_index, data));
+		LOGINT("\"%s\": %c : Master Interrupt Control - Channel B reset  %02x\n", m_owner->tag(), 'A' + m_index, data);
 		m_uart->m_chanB->reset();
 		break;
 	case WR9_CMD_CHNA_RESET:
-		LOGINT(("\"%s\": %c : Master Interrupt Control - Channel A reset  %02x\n", m_owner->tag(), 'A' + m_index, data));
+		LOGINT("\"%s\": %c : Master Interrupt Control - Channel A reset  %02x\n", m_owner->tag(), 'A' + m_index, data);
 		m_uart->m_chanA->reset();
 		break;
 	case WR9_CMD_HW_RESET:
-		LOGINT(("\"%s\": %c : Master Interrupt Control - Device reset  %02x\n", m_owner->tag(), 'A' + m_index, data));
+		LOGINT("\"%s\": %c : Master Interrupt Control - Device reset  %02x\n", m_owner->tag(), 'A' + m_index, data);
 		/*"The effects of this command are identical to those of a hardware reset, except that the Shift Right/Shift Left bit is
 		  not changed and the MIE, Status High/Status Low and DLC bits take the programmed values that accompany this command."
 		*/
@@ -1951,16 +1944,16 @@ void z80scc_channel::do_sccreg_wr9(uint8_t data)
 void z80scc_channel::do_sccreg_wr10(uint8_t data)
 {
 	m_wr10 = data;
-	LOG(("\"%s\": %c : %s Misc Tx/Rx Control %02x - not implemented \n", m_owner->tag(), 'A' + m_index, FUNCNAME, data));
-	LOG(("- 6/8 bit sync %d\n", data & WR10_8_6_BIT_SYNC ? 1 : 0));
-	LOG(("- Loop Mode %d\n", data & WR10_LOOP_MODE ? 1 : 0));
-	LOG(("- Abort/Flag on underrun %d\n", data & WR10_ABORT_FLAG_UNDERRUN ? 1 : 0));
-	LOG(("- Mark/Flag Idle line %d\n", data & WR10_MARK_FLAG_IDLE ? 1 : 0));
-	LOG(("- Go active on poll %d\n", data & WR10_GO_ACTIVE_ON_POLL ? 1 : 0));
-	LOG(("- Encoding %s\n", data & WR10_BIT6 ?
+	LOG("\"%s\": %c : %s Misc Tx/Rx Control %02x - not implemented \n", m_owner->tag(), 'A' + m_index, FUNCNAME, data);
+	LOG("- 6/8 bit sync %d\n", data & WR10_8_6_BIT_SYNC ? 1 : 0);
+	LOG("- Loop Mode %d\n", data & WR10_LOOP_MODE ? 1 : 0);
+	LOG("- Abort/Flag on underrun %d\n", data & WR10_ABORT_FLAG_UNDERRUN ? 1 : 0);
+	LOG("- Mark/Flag Idle line %d\n", data & WR10_MARK_FLAG_IDLE ? 1 : 0);
+	LOG("- Go active on poll %d\n", data & WR10_GO_ACTIVE_ON_POLL ? 1 : 0);
+	LOG("- Encoding %s\n", data & WR10_BIT6 ?
 		 (data & WR10_BIT5 ? "FM0"  : "FM1") :
-		 (data & WR10_BIT5 ? "NRZI" : "NRZ") ));
-	LOG(("- CRC Preset %d\n", data & WR10_CRC_PRESET ? 1 : 0));
+		 (data & WR10_BIT5 ? "NRZI" : "NRZ"));
+	LOG("- CRC Preset %d\n", data & WR10_CRC_PRESET ? 1 : 0);
 }
 
 /* WR11 is the Clock Mode Control register. The bits in this register control the sources of both the
@@ -1968,7 +1961,7 @@ receive and transmit clocks, the type of signal on the /SYNC and /RTxC pins, and
 the /TRxC pin.*/
 void z80scc_channel::do_sccreg_wr11(uint8_t data)
 {
-	LOG(("\"%s\": %c : %s Clock Mode Control %02x\n", m_owner->tag(), 'A' + m_index, FUNCNAME, data));
+	LOG("\"%s\": %c : %s Clock Mode Control %02x\n", m_owner->tag(), 'A' + m_index, FUNCNAME, data);
 	m_wr11 = data;
 	/*Bit 7: This bit controls the type of input signal the SCC expects to see on the /RTxC pin. If this bit is set
 	  to 0, the SCC expects a TTL-compatible signal as an input to this pin. If this bit is set to 1, the SCC
@@ -1978,19 +1971,19 @@ void z80scc_channel::do_sccreg_wr11(uint8_t data)
 	  /SYNC pin is unavailable for other use. The /SYNC signal is forced to zero internally. A hardware
 	  reset forces /NO XTAL. (At least 20 ms should be allowed after this bit is set to allow the oscillator
 	  to stabilize.)*/
-	LOG(("  Clock type %s\n", data & WR11_RCVCLK_TYPE ? "Crystal oscillator between RTxC and /SYNC pins" : "TTL level on RTxC pin and /SYNC can be used"));
+	LOG("  Clock type %s\n", data & WR11_RCVCLK_TYPE ? "Crystal oscillator between RTxC and /SYNC pins" : "TTL level on RTxC pin and /SYNC can be used");
 	/*Bits 6 and 5: Receiver Clock select bits 1 and 0
 	  These bits determine the source of the receive clock as listed below. They do not
 	  interfere with any of the modes of operation in the SCC, but simply control a multiplexer just
 	  before the internal receive clock input. A hardware reset forces the receive clock to come from the
 	  /RTxC pin.*/
-	LOG(("  Receive clock source is: "));
+	LOG("  Receive clock source is: ");
 	switch (data & WR11_RCVCLK_SRC_MASK)
 	{
-	case WR11_RCVCLK_SRC_RTXC: LOG(("RTxC - not implemented\n")); break;
-	case WR11_RCVCLK_SRC_TRXC: LOG(("TRxC - not implemented\n")); break;
-	case WR11_RCVCLK_SRC_BR:   LOG(("Baudrate Generator\n")); break;
-	case WR11_RCVCLK_SRC_DPLL: LOG(("DPLL - not implemented\n")); break;
+	case WR11_RCVCLK_SRC_RTXC: LOG("RTxC - not implemented\n"); break;
+	case WR11_RCVCLK_SRC_TRXC: LOG("TRxC - not implemented\n"); break;
+	case WR11_RCVCLK_SRC_BR:   LOG("Baudrate Generator\n"); break;
+	case WR11_RCVCLK_SRC_DPLL: LOG("DPLL - not implemented\n"); break;
 	default: logerror("Wrong!\n");/* Will not happen unless someone messes with the mask */
 	}
 	/*Bits 4 and 3: Transmit Clock select bits 1 and 0.
@@ -2000,13 +1993,13 @@ void z80scc_channel::do_sccreg_wr11(uint8_t data)
 	  degrees the output of the DPLL used by the receiver. This makes the received and transmitted bit
 	  cells occur simultaneously, neglecting delays. A hardware reset selects the /TRxC pin as the
 	  source of the transmit clocks.*/
-	LOG(("  Transmit clock source is: "));
+	LOG("  Transmit clock source is: ");
 	switch (data & WR11_TRACLK_SRC_MASK)
 	{
-	case WR11_TRACLK_SRC_RTXC: LOG(("RTxC - not implemented\n")); break;
-	case WR11_TRACLK_SRC_TRXC: LOG(("TRxC - not implemented\n")); break;
-	case WR11_TRACLK_SRC_BR:   LOG(("Baudrate Generator\n")); break;
-	case WR11_TRACLK_SRC_DPLL: LOG(("DPLL - not implemented\n")); break;
+	case WR11_TRACLK_SRC_RTXC: LOG("RTxC - not implemented\n"); break;
+	case WR11_TRACLK_SRC_TRXC: LOG("TRxC - not implemented\n"); break;
+	case WR11_TRACLK_SRC_BR:   LOG("Baudrate Generator\n"); break;
+	case WR11_TRACLK_SRC_DPLL: LOG("DPLL - not implemented\n"); break;
 	default: logerror("Wrong!\n");/* Will not happen unless someone messes with the mask */
 	}
 	/* Bit 2: TRxC Pin I/O control bit
@@ -2015,7 +2008,7 @@ void z80scc_channel::do_sccreg_wr11(uint8_t data)
 	   transmit clock is programmed to come from the /TRxC pin, /TRxC is an input, regardless of the
 	   state of this bit. The /TRxC pin is also an input if this bit is set to 0. A hardware reset forces this bit
 	   to 0.*/
-	LOG(("  TRxC pin is %s\n", data & WR11_TRXC_DIRECTION ? "Output" : "Input"));
+	LOG("  TRxC pin is %s\n", data & WR11_TRXC_DIRECTION ? "Output" : "Input");
 	/*Bits 1 and 0: /TRxC Output Source select bits 1 and 0
 	  These bits determine the signal to be echoed out of the SCC via the /TRxC pin as listed in Table
 	  on page 167. No signal is produced if /TRxC has been programmed as the source of either the
@@ -2025,13 +2018,13 @@ void z80scc_channel::do_sccreg_wr11(uint8_t data)
 	  Hardware reset selects the XTAL oscillator as the output source*/
 	if (data & WR11_TRXC_DIRECTION)
 	{
-	LOG(("  TRxC pin output is: "));
+	LOG("  TRxC pin output is: ");
 		switch (data & WR11_TRXSRC_SRC_MASK)
 		{
-		case WR11_TRXSRC_SRC_XTAL: LOG(("the Oscillator - not implemented\n")); break;
-		case WR11_TRXSRC_SRC_TRA:  LOG(("Transmit clock - not_implemented\n")); break;
-		case WR11_TRXSRC_SRC_BR:   LOG(("Baudrate Generator\n")); break;
-		case WR11_TRXSRC_SRC_DPLL: LOG(("DPLL - not implemented\n")); break;
+		case WR11_TRXSRC_SRC_XTAL: LOG("the Oscillator - not implemented\n"); break;
+		case WR11_TRXSRC_SRC_TRA:  LOG("Transmit clock - not_implemented\n"); break;
+		case WR11_TRXSRC_SRC_BR:   LOG("Baudrate Generator\n"); break;
+		case WR11_TRXSRC_SRC_DPLL: LOG("DPLL - not implemented\n"); break;
 		default: logerror("Wrong!\n");/* Will not happen unless someone messes with the mask */
 		}
 	}
@@ -2056,7 +2049,7 @@ void z80scc_channel::do_sccreg_wr12(uint8_t data)
 {
 	m_wr12 = data;
 	update_serial();
-	LOG(("\"%s\": %c : %s  %02x Low byte of Time Constant for Baudrate generator\n", m_owner->tag(), 'A' + m_index, FUNCNAME, data));
+	LOG("\"%s\": %c : %s  %02x Low byte of Time Constant for Baudrate generator\n", m_owner->tag(), 'A' + m_index, FUNCNAME, data);
 }
 
 /* WR13 contains the upper byte of the time constant for the baud rate generator. */
@@ -2064,7 +2057,7 @@ void z80scc_channel::do_sccreg_wr13(uint8_t data)
 {
 	m_wr13 = data;
 	update_serial();
-	LOG(("\"%s\": %c : %s  %02x  High byte of Time Constant for Baudrate generator\n", m_owner->tag(), 'A' + m_index, FUNCNAME, data));
+	LOG("\"%s\": %c : %s  %02x  High byte of Time Constant for Baudrate generator\n", m_owner->tag(), 'A' + m_index, FUNCNAME, data);
 }
 
 /*
@@ -2074,7 +2067,7 @@ void z80scc_channel::do_sccreg_wr14(uint8_t data)
 	switch (data & WR14_DPLL_CMD_MASK)
 	{
 	case WR14_CMD_NULL:
-		LOG(("\"%s\": %c : %s  Misc Control Bits Null Command %02x\n", m_owner->tag(), 'A' + m_index, FUNCNAME, data));
+		LOG("\"%s\": %c : %s  Misc Control Bits Null Command %02x\n", m_owner->tag(), 'A' + m_index, FUNCNAME, data);
 		break;
 	case WR14_CMD_ESM:
 /* Issuing this command causes the DPLL to enter the Search mode, where the DPLL searches for a locking edge in the
@@ -2096,44 +2089,44 @@ void z80scc_channel::do_sccreg_wr14(uint8_t data)
    see an edge during the expected window, the one clock missing bit in RR10 is set. If the DPLL does not see an edge
    after two successive attempts, the two clocks missing bits in RR10 are set and the DPLL automatically enters the
    Search mode. This command resets both clocks missing latches.*/
-		LOG(("\"%s\": %c : %s  Misc Control Bits Enter Search Mode Command - not implemented\n", m_owner->tag(), 'A' + m_index, FUNCNAME));
+		LOG("\"%s\": %c : %s  Misc Control Bits Enter Search Mode Command - not implemented\n", m_owner->tag(), 'A' + m_index, FUNCNAME);
 		break;
 	case WR14_CMD_RMC:
 		/* Issuing this command disables the DPLL, resets the clock missing latches in RR10, and forces a continuous Search mode state */
-		LOG(("\"%s\": %c : %s  Misc Control Bits Reset Missing Clocks Command - not implemented\n", m_owner->tag(), 'A' + m_index, FUNCNAME));
+		LOG("\"%s\": %c : %s  Misc Control Bits Reset Missing Clocks Command - not implemented\n", m_owner->tag(), 'A' + m_index, FUNCNAME);
 		break;
 	case WR14_CMD_DISABLE_DPLL:
 		/* Issuing this command disables the DPLL, resets the clock missing latches in RR10, and forces a continuous Search mode state.*/
-		LOG(("\"%s\": %c : %s  Misc Control Bits Disable DPLL Command - not implemented\n", m_owner->tag(), 'A' + m_index, FUNCNAME));
+		LOG("\"%s\": %c : %s  Misc Control Bits Disable DPLL Command - not implemented\n", m_owner->tag(), 'A' + m_index, FUNCNAME);
 		break;
 	case WR14_CMD_SS_BRG:
 		/* Issuing this command forces the clock for the DPLL to come from the output of the BRG. */
-		LOG(("\"%s\": %c : %s  Misc Control Bits Baudrate Generator Input DPLL Command - not implemented\n", m_owner->tag(), 'A' + m_index, FUNCNAME));
+		LOG("\"%s\": %c : %s  Misc Control Bits Baudrate Generator Input DPLL Command - not implemented\n", m_owner->tag(), 'A' + m_index, FUNCNAME);
 		break;
 	case WR14_CMD_SS_RTXC:
 		/* Issuing the command forces the clock for the DPLL to come from the /RTxC pin or the crystal oscillator, depending on
 		   the state of the XTAL/no XTAL bit in WR11. This mode is selected by a channel or hardware reset*/
-		LOG(("\"%s\": %c : %s  Misc Control Bits RTxC Input DPLL Command - not implemented\n", m_owner->tag(), 'A' + m_index, FUNCNAME));
+		LOG("\"%s\": %c : %s  Misc Control Bits RTxC Input DPLL Command - not implemented\n", m_owner->tag(), 'A' + m_index, FUNCNAME);
 		break;
 	case WR14_CMD_SET_FM:
 		/* This command forces the DPLL to operate in the FM mode and is used to recover the clock from FM or Manchester-Encoded
 		   data. (Manchester is decoded by placing the receiver in NRZ mode while the DPLL is in FM mode.)*/
-		LOG(("\"%s\": %c : %s  Misc Control Bits Set FM Mode Command - not implemented\n", m_owner->tag(), 'A' + m_index, FUNCNAME));
+		LOG("\"%s\": %c : %s  Misc Control Bits Set FM Mode Command - not implemented\n", m_owner->tag(), 'A' + m_index, FUNCNAME);
 		break;
 	case WR14_CMD_SET_NRZI:
 		/* Issuing this command forces the DPLL to operate in the NRZI mode. This mode is also selected by a hardware or channel reset.*/
-		LOG(("\"%s\": %c : %s  Mics Control Bits Set NRZI Mode Command - not implemented\n", m_owner->tag(), 'A' + m_index, FUNCNAME));
+		LOG("\"%s\": %c : %s  Mics Control Bits Set NRZI Mode Command - not implemented\n", m_owner->tag(), 'A' + m_index, FUNCNAME);
 		break;
 	default:
 		logerror("\"%s\": %c : %s Mics Control Bits command %02x - not implemented \n", m_owner->tag(), 'A' + m_index, FUNCNAME, data);
 	}
 	/* Based on baudrate code from 8530scc.cpp */
-	if ( !(m_wr14 & WR14_BRG_ENABLE) && (data & WR14_BRG_ENABLE) ) // baud rate generator beeing enabled?
+	if ( !(m_wr14 & WR14_BRG_ENABLE) && (data & WR14_BRG_ENABLE) ) // baud rate generator being enabled?
 	{
-		LOG(("\"%s\": %c : %s Mics Control Bits Baudrate generator enabled with ", m_owner->tag(), 'A' + m_index, FUNCNAME));
+		LOG("\"%s\": %c : %s Mics Control Bits Baudrate generator enabled with ", m_owner->tag(), 'A' + m_index, FUNCNAME);
 		if (data & WR14_BRG_SOURCE) // Do we use the PCLK as baudrate source
 		{
-			LOG(("   - PCLK as source\n"));
+			LOG("   - PCLK as source\n");
 
 #if LOCAL_BRG
 			baudtimer->adjust(attotime::from_hz(rate), TIMER_ID_BAUD, attotime::from_hz(rate)); // Start the baudrate generator
@@ -2144,10 +2137,10 @@ void z80scc_channel::do_sccreg_wr14(uint8_t data)
 		}
 		else
 		{
-			LOG(("external clock source\n"));
+			LOG("external clock source\n");
 		}
 	}
-	else if ( (m_wr14 & WR14_BRG_ENABLE) && !(data & WR14_BRG_ENABLE) ) // baud rate generator beeing disabled?
+	else if ( (m_wr14 & WR14_BRG_ENABLE) && !(data & WR14_BRG_ENABLE) ) // baud rate generator being disabled?
 	{
 #if LOCAL_BRG
 		baudtimer->adjust(attotime::never, TIMER_ID_BAUD, attotime::never); // Stop the baudrate generator
@@ -2167,16 +2160,16 @@ void z80scc_channel::do_sccreg_wr14(uint8_t data)
 #define WR15NO "not implemented"
 void z80scc_channel::do_sccreg_wr15(uint8_t data)
 {
-	LOG(("%s(%02x) \"%s\": %c : External/Status Control Bits\n",
-			FUNCNAME, data, m_owner->tag(), 'A' + m_index));
-	LOG(("WR7 prime ints     : %s\n", data & WR15_WR7PRIME    ? WR15NO : "disabled"));
-	LOG(("Zero count ints    : %s\n", data & WR15_ZEROCOUNT   ? WR15NO : "disabled"));
-	LOG(("14 bit Status FIFO : %s\n", data & WR15_STATUS_FIFO ? WR15NO : "disabled"));
-	LOG(("DCD ints           : %s\n", data & WR15_DCD         ? WR15EN : "disabled"));
-	LOG(("SYNC/Hunt ints     : %s\n", data & WR15_SYNC        ? WR15NO : "disabled"));
-	LOG(("CTS ints           : %s\n", data & WR15_CTS         ? WR15EN : "disabled"));
-	LOG(("Tx underr./EOM ints: %s\n", data & WR15_TX_EOM      ? WR15NO : "disabled"));
-	LOG(("Break/Abort ints   : %s\n", data & WR15_BREAK_ABORT ? WR15NO : "disabled"));
+	LOG("%s(%02x) \"%s\": %c : External/Status Control Bits\n",
+			FUNCNAME, data, m_owner->tag(), 'A' + m_index);
+	LOG("WR7 prime ints     : %s\n", data & WR15_WR7PRIME    ? WR15NO : "disabled");
+	LOG("Zero count ints    : %s\n", data & WR15_ZEROCOUNT   ? WR15NO : "disabled");
+	LOG("14 bit Status FIFO : %s\n", data & WR15_STATUS_FIFO ? WR15NO : "disabled");
+	LOG("DCD ints           : %s\n", data & WR15_DCD         ? WR15EN : "disabled");
+	LOG("SYNC/Hunt ints     : %s\n", data & WR15_SYNC        ? WR15NO : "disabled");
+	LOG("CTS ints           : %s\n", data & WR15_CTS         ? WR15EN : "disabled");
+	LOG("Tx underr./EOM ints: %s\n", data & WR15_TX_EOM      ? WR15NO : "disabled");
+	LOG("Break/Abort ints   : %s\n", data & WR15_BREAK_ABORT ? WR15NO : "disabled");
 	m_wr15 = data;
 }
 
@@ -2241,8 +2234,8 @@ void z80scc_channel::control_write(uint8_t data)
 		m_wr0 &= ~regmask;
 	}
 
-	//LOG(("\n%s(%02x) reg %02x, regmask %02x\n", FUNCNAME, data, reg, regmask));
-	LOGSETUP((" * %s %c Reg %02x <- %02x  \n", m_owner->tag(), 'A' + m_index, reg, data));
+	//LOG("\n%s(%02x) reg %02x, regmask %02x\n", FUNCNAME, data, reg, regmask);
+	LOGSETUP(" * %s %c Reg %02x <- %02x  \n", m_owner->tag(), 'A' + m_index, reg, data);
 
 	scc_register_write(reg, data);
 }
@@ -2256,7 +2249,7 @@ uint8_t z80scc_channel::data_read()
 {
 	uint8_t data = 0;
 
-	LOG(("%s \"%s\": %c : Data Register Read: ", FUNCNAME, m_owner->tag(), 'A' + m_index));
+	LOG("%s \"%s\": %c : Data Register Read: ", FUNCNAME, m_owner->tag(), 'A' + m_index);
 
 	if (m_rx_fifo_wp != m_rx_fifo_rp)
 	{
@@ -2275,29 +2268,16 @@ uint8_t z80scc_channel::data_read()
 		   received into the other bytes of the Receive FIFO.*/
 
 		// load data from the FIFO
-		data = m_rx_fifo_rp_data();
+		data = m_rx_data_fifo[m_rx_fifo_rp];
 
 		// load error status from the FIFO
-		m_rr1 = (m_rr1 & ~(RR1_CRC_FRAMING_ERROR | RR1_RX_OVERRUN_ERROR | RR1_PARITY_ERROR)) | m_rx_error_fifo[m_rx_fifo_rp]; //  TODO: Status FIFO needs to be fixed
+		m_rr1 = (m_rr1 & ~(RR1_CRC_FRAMING_ERROR | RR1_RX_OVERRUN_ERROR | RR1_PARITY_ERROR)) | m_rx_error_fifo[m_rx_fifo_rp];
 
-		// trigger interrup and lock the fifo if an error is present
-		if (m_rr1 & (RR1_CRC_FRAMING_ERROR | RR1_RX_OVERRUN_ERROR | RR1_PARITY_ERROR))
+		// trigger interrupt and lock the fifo if an error is present
+		if (m_rr1 & (RR1_CRC_FRAMING_ERROR | RR1_RX_OVERRUN_ERROR | ((m_wr1 & WR1_PARITY_IS_SPEC_COND) ? RR1_PARITY_ERROR : 0)))
 		{
 			logerror("Rx Error %02x\n", m_rr1 & (RR1_CRC_FRAMING_ERROR | RR1_RX_OVERRUN_ERROR | RR1_PARITY_ERROR));
-			switch (m_wr1 & WR1_RX_INT_MODE_MASK)
-			{
-			case WR1_RX_INT_FIRST:
-				if (!m_rx_first)
-				{
-					m_uart->trigger_interrupt(m_index, INT_SPECIAL);
-				}
-				break;
-
-			case WR1_RX_INT_ALL_PARITY:
-			case WR1_RX_INT_ALL:
-				m_uart->trigger_interrupt(m_index, INT_SPECIAL);
-				break;
-			}
+			m_uart->trigger_interrupt(m_index, INT_SPECIAL);
 		}
 		else
 		{
@@ -2307,26 +2287,14 @@ uint8_t z80scc_channel::data_read()
 	}
 	else
 	{
-		LOG(("data_read: Attempt to read out character from empty FIFO\n"));
+		LOG("data_read: Attempt to read out character from empty FIFO\n");
 		logerror("data_read: Attempt to read out character from empty FIFO\n");
 	}
 
-	LOG(("  '%c' %02x\n", isascii(data) ? data : ' ', data));
+	LOG("  '%c' %02x\n", isascii(data) ? data : ' ', data);
 	return data;
 }
 
-/* Get data from top of fifo data but restore read pointer in case of exit latch lock */
-uint8_t z80scc_channel::m_rx_fifo_rp_data()
-{
-		uint8_t data;
-		uint8_t old_rp = m_rx_fifo_rp;
-		m_rx_fifo_rp_step();
-		data = m_rx_data_fifo[m_rx_fifo_rp];
-		m_rx_fifo_rp = old_rp;
-
-		return data;
-}
-
 /* Step read pointer */
 void z80scc_channel::m_rx_fifo_rp_step()
 {
@@ -2365,17 +2333,17 @@ WRITE8_MEMBER (z80scc_device::db_w) { m_chanB->data_write(data); }
 void z80scc_channel::data_write(uint8_t data)
 {
 	/* Tx FIFO is full or...? */
-	LOGTX(("%s \"%s\": %c : Data Register Write: %02d '%c'\n", FUNCNAME, m_owner->tag(), 'A' + m_index, data, isprint(data) ? data : ' '));
+	LOGTX("%s \"%s\": %c : Data Register Write: %02d '%c'\n", FUNCNAME, m_owner->tag(), 'A' + m_index, data, isprint(data) ? data : ' ');
 
 	if ( !(m_rr0 & RR0_TX_BUFFER_EMPTY) && // NMOS/CMOS 1 slot "FIFO" is controlled by the TBE bit instead of fifo logic
 		( (m_tx_fifo_wp + 1 == m_tx_fifo_rp) || ( (m_tx_fifo_wp + 1 == m_tx_fifo_sz) && (m_tx_fifo_rp == 0) )))
 	{
 		logerror("- TX FIFO is full, discarding data\n");
-		LOGTX(("- TX FIFO is full, discarding data\n"));
+		LOGTX("- TX FIFO is full, discarding data\n");
 	}
 	else // ..there is still room
 	{
-		LOGTX(("- TX FIFO has room\n"));
+		LOGTX("- TX FIFO has room\n");
 		m_tx_data_fifo[m_tx_fifo_wp++] = data;
 		if (m_tx_fifo_wp >= m_tx_fifo_sz)
 		{
@@ -2385,30 +2353,30 @@ void z80scc_channel::data_write(uint8_t data)
 		// Check FIFO fullness and set TBE bit accordingly
 		if (m_tx_fifo_sz == 1)
 		{
-			LOGTX(("- TX FIFO has only one slot so is now completelly filled, clearing TBE bit\n"));
+			LOGTX("- TX FIFO has only one slot so is now completelly filled, clearing TBE bit\n");
 			m_rr0 &= ~RR0_TX_BUFFER_EMPTY; // If only one FIFO position it is full now!
 		}
 		else if (m_tx_fifo_wp + 1 == m_tx_fifo_rp || ( (m_tx_fifo_wp + 1 == m_tx_fifo_sz) && (m_tx_fifo_rp == 0) ))
 		{
-			LOGTX(("- TX FIFO has filled all slots so now completelly filled, clearing TBE bit\n"));
+			LOGTX("- TX FIFO has filled all slots so now completelly filled, clearing TBE bit\n");
 			m_rr0 &= ~RR0_TX_BUFFER_EMPTY; // Indicate that the TX fifo is full
 		}
 		else
 		{
-			LOGTX(("- TX FIFO has more room, setting TBE bit\n"));
+			LOGTX("- TX FIFO has more room, setting TBE bit\n");
 			m_rr0 |= RR0_TX_BUFFER_EMPTY; // or there is a slot in the FIFO available
 		}
-		LOGTX(("- TX FIFO now has data to send, clearing ALL_SENT bit\n"));
+		LOGTX("- TX FIFO now has data to send, clearing ALL_SENT bit\n");
 		m_rr1 &= ~RR1_ALL_SENT; // All is definitelly not sent anymore
 	}
 
 	/* Transmitter enabled?  */
 	if (m_wr5 & WR5_TX_ENABLE)
 	{
-		LOGTX(("- TX is enabled\n"));
+		LOGTX("- TX is enabled\n");
 		if (is_transmit_register_empty()) // Is the shift register loaded?
 		{
-			LOGTX(("- Setting up transmitter\n"));
+			LOGTX("- Setting up transmitter\n");
 			transmit_register_setup(m_tx_data_fifo[m_tx_fifo_rp]); // Load the shift register, reload is done in tra_complete()
 			m_tx_fifo_rp_step();
 			m_rr1 |= RR1_ALL_SENT; // Now stuff is on its way again
@@ -2416,19 +2384,19 @@ void z80scc_channel::data_write(uint8_t data)
 		}
 		else
 		{
-			LOGTX(("- Transmitter not empty\n"));
+			LOGTX("- Transmitter not empty\n");
 		}
 	}
 	else
 	{
-		LOGTX(("- Transmitter disabled\n"));
+		LOGTX("- Transmitter disabled\n");
 	}
 	/* "While transmit interrupts are enabled, the nmos/cmos version sets the transmit interrupt pending
 	   (TxIP) bit whenever the transmit buffer becomes empty. this means that the transmit buffer
 	   must be full before the TxIP can be set. thus, when transmit interrupts are first enabled, the TxIP
 	   will not be set until after the first character is written to the nmos/cmos." */
 	// check if to fire interrupt
-	LOG(("- TX interrupt are %s\n", (m_wr1 & WR1_TX_INT_ENABLE) ? "enabled" : "disabled" ));
+	LOG("- TX interrupt are %s\n", (m_wr1 & WR1_TX_INT_ENABLE) ? "enabled" : "disabled" );
 	if (m_wr1 & WR1_TX_INT_ENABLE)
 	{
 		if ((m_uart->m_variant & SET_ESCC) &&
@@ -2446,22 +2414,30 @@ void z80scc_channel::data_write(uint8_t data)
 
 
 //-------------------------------------------------
-//  receive_data - receive data word into fifo
+//  receive_data - put received data word into fifo
 //-------------------------------------------------
 
 void z80scc_channel::receive_data(uint8_t data)
 {
-	LOG(("\"%s\": %c : Receive Data Byte '%02x'\n", m_owner->tag(), 'A' + m_index, data));
+	LOG("\"%s\": %c : Received Data Byte '%c'/%02x put into FIFO\n", m_owner->tag(), 'A' + m_index, isprint(data) ? data : ' ', data);
 
 	if (m_rx_fifo_wp + 1 == m_rx_fifo_rp || ( (m_rx_fifo_wp + 1 == m_rx_fifo_sz) && (m_rx_fifo_rp == 0) ))
 	{
 		// receive overrun error detected
-		m_rx_error_fifo[m_rx_fifo_wp] |= RR1_RX_OVERRUN_ERROR; // = m_rx_error;  TODO: Status FIFO needs to be fixed
+		m_rx_error_fifo[m_rx_fifo_wp] |= RR1_RX_OVERRUN_ERROR;
+
+		// store received character but do not step the fifo
+		m_rx_data_fifo[m_rx_fifo_wp] = data;
+
 		logerror("Receive_data() Error %02x\n", m_rx_error_fifo[m_rx_fifo_wp] & (RR1_CRC_FRAMING_ERROR | RR1_RX_OVERRUN_ERROR | RR1_PARITY_ERROR));
 	}
 	else
 	{
-		m_rx_error_fifo[m_rx_fifo_wp] &= ~RR1_RX_OVERRUN_ERROR; // = m_rx_error;  TODO: Status FIFO needs to be fixed
+		m_rx_error_fifo[m_rx_fifo_wp] &= ~RR1_RX_OVERRUN_ERROR;
+
+		// store received character
+		m_rx_data_fifo[m_rx_fifo_wp] = data;
+
 		m_rx_fifo_wp++;
 		if (m_rx_fifo_wp >= m_rx_fifo_sz)
 		{
@@ -2469,13 +2445,9 @@ void z80scc_channel::receive_data(uint8_t data)
 		}
 	}
 
-	// store received character
-	m_rx_data_fifo[m_rx_fifo_wp] = data;
-
 	m_rr0 |= RR0_RX_CHAR_AVAILABLE;
 
-#if 0 // interrupt on exit from fifo
-	// receive interrupt
+	// receive interrupt on FIRST and ALL character
 	switch (m_wr1 & WR1_RX_INT_MODE_MASK)
 	{
 	case WR1_RX_INT_FIRST:
@@ -2487,12 +2459,10 @@ void z80scc_channel::receive_data(uint8_t data)
 		}
 		break;
 
-	case WR1_RX_INT_ALL_PARITY:
 	case WR1_RX_INT_ALL:
 		m_uart->trigger_interrupt(m_index, INT_RECEIVE);
 		break;
 	}
-#endif
 }
 
 
@@ -2502,17 +2472,17 @@ void z80scc_channel::receive_data(uint8_t data)
 
 WRITE_LINE_MEMBER( z80scc_channel::cts_w )
 {
-	LOG(("\"%s\" %s: %c : CTS %u\n", m_owner->tag(), FUNCNAME, 'A' + m_index, state));
+	LOG("\"%s\" %s: %c : CTS %u\n", m_owner->tag(), FUNCNAME, 'A' + m_index, state);
 
 	if ((m_rr0 & RR0_CTS) != (state ? RR0_CTS : 0)) //  SCC change detection logic
 	{
 		// enable transmitter if in auto enables mode
 		if (!state)
 		{
-			LOGCTS((" - CTS active\n"));
+			LOGCTS(" - CTS active\n");
 			if (m_wr3 & WR3_AUTO_ENABLES)
 			{
-				LOGCTS((" - TX auto enabled\n"));
+				LOGCTS(" - TX auto enabled\n");
 				m_wr5 |= WR5_TX_ENABLE;
 			}
 		}
@@ -2522,11 +2492,11 @@ WRITE_LINE_MEMBER( z80scc_channel::cts_w )
 		if (m_extint_latch == 0 && (m_wr1 & WR1_EXT_INT_ENABLE) && (m_wr15 & WR15_CTS))
 		{
 			// trigger interrupt
-			LOGCTS((" - Trigger CTS interrupt\n"));
+			LOGCTS(" - Trigger CTS interrupt\n");
 			m_uart->trigger_interrupt(m_index, INT_EXTERNAL);
 
 			// latch read register 0
-			LOGCTS((" - Latches RR0\n"));
+			LOGCTS(" - Latches RR0\n");
 			m_extint_latch = 1;
 			m_extint_states = m_rr0;
 		}
@@ -2539,17 +2509,17 @@ WRITE_LINE_MEMBER( z80scc_channel::cts_w )
 //-------------------------------------------------
 WRITE_LINE_MEMBER( z80scc_channel::dcd_w )
 {
-	LOGDCD(("\"%s\": %c : DCD %u\n", m_owner->tag(), 'A' + m_index, state));
+	LOGDCD("\"%s\": %c : DCD %u\n", m_owner->tag(), 'A' + m_index, state);
 
 	if ((m_rr0 & RR0_DCD) != (state ? RR0_DCD : 0)) //  SCC change detection logic
 	{
 		// enable transmitter if in auto enables mode
 		if (!state)
 		{
-			LOGDCD((" - DCD active\n"));
+			LOGDCD(" - DCD active\n");
 			if (m_wr3 & WR3_AUTO_ENABLES)
 			{
-				LOGDCD((" - RX auto enabled\n"));
+				LOGDCD(" - RX auto enabled\n");
 				m_wr3 |= WR3_RX_ENABLE;
 #if START_BIT_HUNT
 				m_rcv_mode = RCV_SEEKING;
@@ -2562,12 +2532,12 @@ WRITE_LINE_MEMBER( z80scc_channel::dcd_w )
 		if (m_extint_latch == 0 && (m_wr1 & WR1_EXT_INT_ENABLE) && (m_wr15 & WR15_DCD))
 		{
 			// latch read register 0
-			LOGINT((" - Latches RR0\n"));
+			LOGINT(" - Latches RR0\n");
 			m_extint_latch = 1;
 			m_extint_states = m_rr0;
 
 			// trigger interrupt
-			LOGINT((" - Trigger DCD interrupt\n"));
+			LOGINT(" - Trigger DCD interrupt\n");
 			m_uart->trigger_interrupt(m_index, INT_EXTERNAL);
 		}
 	}
@@ -2579,7 +2549,7 @@ WRITE_LINE_MEMBER( z80scc_channel::dcd_w )
 //-------------------------------------------------
 WRITE_LINE_MEMBER( z80scc_channel::ri_w )
 {
-	LOGINT(("\"%s\": %c : RI %u - not implemented\n", m_owner->tag(), 'A' + m_index, state));
+	LOGINT("\"%s\": %c : RI %u - not implemented\n", m_owner->tag(), 'A' + m_index, state);
 
 #if 0 // TODO: This code is inherited from another device driver and not correct for SCC
 	if (m_ri != state)
@@ -2612,7 +2582,7 @@ WRITE_LINE_MEMBER( z80scc_channel::ri_w )
 //-------------------------------------------------
 WRITE_LINE_MEMBER( z80scc_channel::sync_w )
 {
-	LOGSYNC(("\"%s\": %c : SYNC %u\n", m_owner->tag(), 'A' + m_index, state));
+	LOGSYNC("\"%s\": %c : SYNC %u\n", m_owner->tag(), 'A' + m_index, state);
 	if ((m_rr0 & RR0_SYNC_HUNT) != (state ? RR0_SYNC_HUNT : 0)) //  SCC change detection logic
 	{
 		if (state) m_rr0 |= RR0_SYNC_HUNT; else  m_rr0 &= ~RR0_SYNC_HUNT; // Raw pin/status value
@@ -2626,7 +2596,7 @@ WRITE_LINE_MEMBER( z80scc_channel::rxc_w )
 {
 /* Support for external clock as source for BRG yet to be finished */
 #if 0
-	//LOG(("\"%s\": %c : Receiver Clock Pulse\n", m_owner->tag(), m_index + 'A'));
+	//LOG("\"%s\": %c : Receiver Clock Pulse\n", m_owner->tag(), m_index + 'A');
 	if ( ((m_wr3 & WR3_RX_ENABLE) | (m_wr5 & WR5_TX_ENABLE)) && m_wr14 & WR14_BRG_ENABLE)
 	{
 		if (!(m_wr14 & WR14_BRG_SOURCE)) // Is the Baud rate Generator driven by RTxC?
@@ -2676,7 +2646,7 @@ WRITE_LINE_MEMBER( z80scc_channel::rxc_w )
 //-------------------------------------------------
 WRITE_LINE_MEMBER( z80scc_channel::txc_w )
 {
-	//LOG(("\"%s\": %c : Transmitter Clock Pulse\n", m_owner->tag(), m_index + 'A'));
+	//LOG("\"%s\": %c : Transmitter Clock Pulse\n", m_owner->tag(), m_index + 'A');
 	if (m_wr5 & WR5_TX_ENABLE)
 	{
 		int clocks = get_clock_mode();
@@ -2726,13 +2696,13 @@ unsigned int z80scc_channel::get_brg_rate()
 	if (m_wr14 & WR14_BRG_SOURCE) // Do we use the PCLK as baudrate source
 	{
 		rate = m_owner->clock() / (brg_const == 0 ? 1 : brg_const);
-		LOG(("   - Source bit rate (%d) = PCLK (%d) / (%d)\n", rate, m_owner->clock(), brg_const));
+		LOG("   - Source bit rate (%d) = PCLK (%d) / (%d)\n", rate, m_owner->clock(), brg_const);
 	}
 	else // Else we use the RTxC as BRG source
 	{
 		unsigned int source = (m_index == z80scc_device::CHANNEL_A) ? m_uart->m_rxca : m_uart->m_rxcb;
 		rate = source / (brg_const == 0 ? 1 : brg_const);
-		LOG(("   - Source bit rate (%d) = RTxC (%d) / (%d)\n", rate, source, brg_const));
+		LOG("   - Source bit rate (%d) = RTxC (%d) / (%d)\n", rate, source, brg_const);
 	}
 
 	return (rate / (2 * get_clock_mode()));
@@ -2759,8 +2729,8 @@ void z80scc_channel::update_serial()
 		parity = PARITY_NONE;
 	}
 
-	LOG((" %s() \"%s \"Channel %c setting data frame %d+%d%c%d\n", FUNCNAME, m_owner->tag(), 'A' + m_index, 1,
-		 data_bit_count, parity == PARITY_NONE ? 'N' : parity == PARITY_EVEN ? 'E' : 'O', (stop_bits + 1) / 2));
+	LOG(" %s() \"%s \"Channel %c setting data frame %d+%d%c%d\n", FUNCNAME, m_owner->tag(), 'A' + m_index, 1,
+		 data_bit_count, parity == PARITY_NONE ? 'N' : parity == PARITY_EVEN ? 'E' : 'O', (stop_bits + 1) / 2);
 
 	set_data_frame(1, data_bit_count, parity, stop_bits);
 
@@ -2772,26 +2742,26 @@ void z80scc_channel::update_serial()
 
 	if  (m_wr14 & WR14_BRG_ENABLE)
 	{
-		LOG(("- BRG enabled\n"));
+		LOG("- BRG enabled\n");
 		m_brg_rate = get_brg_rate();
 
-		LOG(("- BRG rate %d\n", m_brg_rate));
+		LOG("- BRG rate %d\n", m_brg_rate);
 		set_rcv_rate(m_brg_rate);
 
 		if (is_transmit_register_empty())
 		{
 			set_tra_rate(m_brg_rate);
-			LOGTX(("   - Baud Rate Generator: %d clock mode: %dx\n", m_brg_rate, get_clock_mode() ));
+			LOGTX("   - Baud Rate Generator: %d clock mode: %dx\n", m_brg_rate, get_clock_mode());
 		}
 		else
 		{
 			m_delayed_tx_brg_change = 1;
-			LOGTX(("   - Baud Rate Generator delay init: %d clock mode: %dx\n", m_brg_rate, get_clock_mode() ));
+			LOGTX("   - Baud Rate Generator delay init: %d clock mode: %dx\n", m_brg_rate, get_clock_mode());
 		}
 	}
 	else
 	{
-		LOG(("- BRG disabled\n"));
+		LOG("- BRG disabled\n");
 		set_rcv_rate(0);
 		set_tra_rate(0);
 	}
@@ -2800,13 +2770,13 @@ void z80scc_channel::update_serial()
 	if (m_rxc > 0)
 	{
 		set_rcv_rate(m_rxc / clocks); // TODO Check/Fix this to get the right tx/rx clocks, seems to be missing a divider or two
-		LOG(("   - Receiver clock: %d mode: %d rate: %d/%xh\n", m_rxc, clocks, m_rxc / clocks, m_rxc / clocks));
+		LOG("   - Receiver clock: %d mode: %d rate: %d/%xh\n", m_rxc, clocks, m_rxc / clocks, m_rxc / clocks);
 	}
 
 	if (m_txc > 0 && !(m_wr14 & WR14_BRG_ENABLE))
 	{
 		set_tra_rate(m_txc / clocks);
-		LOG(("   - Transmit clock: %d mode: %d rate: %d/%xh\n", m_rxc, clocks, m_rxc / clocks, m_rxc / clocks));
+		LOG("   - Transmit clock: %d mode: %d rate: %d/%xh\n", m_rxc, clocks, m_rxc / clocks, m_rxc / clocks);
 	}
 }
 
@@ -2815,7 +2785,7 @@ void z80scc_channel::update_serial()
 //-------------------------------------------------
 void z80scc_channel::set_dtr(int state)
 {
-	LOG(("%s(%d)\n", FUNCNAME, state));
+	LOG("%s(%d)\n", FUNCNAME, state);
 	m_dtr = state;
 
 	if (m_index == z80scc_device::CHANNEL_A)
@@ -2840,7 +2810,7 @@ WRITE_LINE_MEMBER(z80scc_channel::write_rx)
 	}
 #endif
 
-	LOGRCV(("%s(%d)\n", FUNCNAME, state));
+	LOGRCV("%s(%d)\n", FUNCNAME, state);
 	m_rxd = state;
 	//only use rx_w when self-clocked
 	if(m_rxc != 0 || m_brg_rate != 0)
diff --git a/src/devices/machine/z80scc.h b/src/devices/machine/z80scc.h
index fa5f806..ce9fa30 100644
--- a/src/devices/machine/z80scc.h
+++ b/src/devices/machine/z80scc.h
@@ -409,8 +409,8 @@ protected:
 		WR1_RX_INT_MODE_MASK    = 0x18,
 		WR1_RX_INT_DISABLE  = 0x00,
 		WR1_RX_INT_FIRST    = 0x08,
-		WR1_RX_INT_ALL_PARITY   = 0x10,
-		WR1_RX_INT_ALL      = 0x18,
+		WR1_RX_INT_ALL      = 0x10,
+		WR1_RX_INT_PARITY   = 0x18,
 		WR1_WRDY_ON_RX_TX   = 0x20,
 		WR1_WRDY_FUNCTION   = 0x40,
 		WR1_WRDY_ENABLE     = 0x80
diff --git a/src/devices/sound/dac76.cpp b/src/devices/sound/dac76.cpp
new file mode 100644
index 0000000..67fc452
--- /dev/null
+++ b/src/devices/sound/dac76.cpp
@@ -0,0 +1,91 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+    PMI DAC-76 COMDAC
+
+    Companding D/A Converter
+
+***************************************************************************/
+
+#include "dac76.h"
+
+
+//**************************************************************************
+//  CONSTEXPR DEFINITIONS
+//**************************************************************************
+
+constexpr int dac76_device::m_level[];
+
+
+//**************************************************************************
+//  DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type DAC76 = &device_creator<dac76_device>;
+
+
+//**************************************************************************
+//  LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+//  dac76_device - constructor
+//-------------------------------------------------
+
+dac76_device::dac76_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+	device_t(mconfig, DAC76, "DAC-76 COMDAC", tag, owner, clock, "dac76", __FILE__),
+	device_sound_interface(mconfig, *this),
+	m_stream(nullptr),
+	m_chord(0),
+	m_step(0),
+	m_sb(false)
+{
+}
+
+//-------------------------------------------------
+//  device_start - device-specific startup
+//-------------------------------------------------
+
+void dac76_device::device_start()
+{
+	// create sound stream
+	m_stream = machine().sound().stream_alloc(*this, 0, 1, machine().sample_rate() * 8);
+
+	// register for save states
+	save_item(NAME(m_chord));
+	save_item(NAME(m_step));
+	save_item(NAME(m_sb));
+}
+
+//-------------------------------------------------
+//  device_reset - device-specific reset
+//-------------------------------------------------
+
+void dac76_device::device_reset()
+{
+	m_chord = 0;
+	m_step = 0;
+	m_sb = false;
+}
+
+//-------------------------------------------------
+//  sound_stream_update - handle update requests for
+//  our sound stream
+//-------------------------------------------------
+
+void dac76_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
+{
+	// get current output level
+	int step_size = (2 << m_chord);
+	stream_sample_t vout = m_level[m_chord] + m_step * step_size;
+
+	// apply sign bit
+	vout *= (m_sb ? +1 : -1);
+
+	// range is 0-8031, normalize to about 0-32768 range
+	vout *= 4;
+
+	for (int i = 0; i < samples; i++)
+		outputs[0][i] = vout;
+}
diff --git a/src/devices/sound/dac76.h b/src/devices/sound/dac76.h
new file mode 100644
index 0000000..b0086b2
--- /dev/null
+++ b/src/devices/sound/dac76.h
@@ -0,0 +1,76 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+    PMI DAC-76 COMDAC
+
+    Companding D/A Converter
+
+              ___ ___
+      E/D  1 |*  u   | 10  VLC
+       SB  2 |       | 11  VR+
+       B1  3 |       | 12  VR-
+       B2  4 |       | 13  V-
+       B3  5 |       | 14  IOE+
+       B4  6 |       | 15  IOE-
+       B5  7 |       | 16  IOD+
+       B6  8 |       | 17  IOD-
+       B7  9 |_______| 18  V+
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __DAC76_H__
+#define __DAC76_H__
+
+#include "emu.h"
+
+
+//**************************************************************************
+//  TYPE DEFINITIONS
+//**************************************************************************
+
+class dac76_device : public device_t, public device_sound_interface
+{
+public:
+	// construction/destruction
+	dac76_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+	// chord
+	DECLARE_WRITE_LINE_MEMBER(b1_w) { m_chord &= ~(1 << 2); m_chord |= (state << 2); };
+	DECLARE_WRITE_LINE_MEMBER(b2_w) { m_chord &= ~(1 << 1); m_chord |= (state << 1); };
+	DECLARE_WRITE_LINE_MEMBER(b3_w) { m_chord &= ~(1 << 0); m_chord |= (state << 0); };
+
+	// step
+	DECLARE_WRITE_LINE_MEMBER(b4_w) { m_step &= ~(1 << 3); m_step |= (state << 3); };
+	DECLARE_WRITE_LINE_MEMBER(b5_w) { m_step &= ~(1 << 2); m_step |= (state << 2); };
+	DECLARE_WRITE_LINE_MEMBER(b6_w) { m_step &= ~(1 << 1); m_step |= (state << 1); };
+	DECLARE_WRITE_LINE_MEMBER(b7_w) { m_step &= ~(1 << 0); m_step |= (state << 0); };
+
+	// sign bit
+	DECLARE_WRITE_LINE_MEMBER(sb_w) { m_sb = bool(state); };
+
+	void update() { m_stream->update(); }
+
+protected:
+	// device-level overrides
+	virtual void device_start() override;
+	virtual void device_reset() override;
+
+	virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
+
+private:
+	static constexpr int m_level[8] = { 0, 33, 99, 231, 495, 1023, 2079, 4191 };
+
+	sound_stream *m_stream;
+
+	uint8_t m_chord; // 4-bit
+	uint8_t m_step; // 3-bit
+	bool m_sb;
+};
+
+// device type definition
+extern const device_type DAC76;
+
+#endif // __DAC76_H__
diff --git a/src/devices/sound/k054539.cpp b/src/devices/sound/k054539.cpp
index c275494..78b6d08 100644
--- a/src/devices/sound/k054539.cpp
+++ b/src/devices/sound/k054539.cpp
@@ -329,9 +329,19 @@ void k054539_device::init_chip()
 
 	stream = stream_alloc(0, 2, clock() / 384);
 
+	save_item(NAME(voltab));
+	save_item(NAME(pantab));
+	save_item(NAME(gain));
+	save_item(NAME(posreg_latch));
+	save_item(NAME(flags));
+
 	save_item(NAME(regs));
 	save_pointer(NAME(ram.get()), 0x4000);
+	save_item(NAME(reverb_pos));
 	save_item(NAME(cur_ptr));
+	save_item(NAME(cur_limit));
+
+	save_item(NAME(m_timer_state));
 }
 
 WRITE8_MEMBER(k054539_device::write)
diff --git a/src/devices/sound/k056800.cpp b/src/devices/sound/k056800.cpp
index 19e572d..fe42ed0 100644
--- a/src/devices/sound/k056800.cpp
+++ b/src/devices/sound/k056800.cpp
@@ -36,6 +36,7 @@ void k056800_device::device_start()
 	m_int_handler.resolve_safe();
 
 	save_item(NAME(m_int_pending));
+	save_item(NAME(m_int_enabled));
 	save_item(NAME(m_host_to_snd_regs));
 	save_item(NAME(m_snd_to_host_regs));
 }
diff --git a/src/devices/sound/mm5837.cpp b/src/devices/sound/mm5837.cpp
new file mode 100644
index 0000000..fc700cd
--- /dev/null
+++ b/src/devices/sound/mm5837.cpp
@@ -0,0 +1,90 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+    National Semiconductor MM5837
+
+    Digital Noise Source
+
+***************************************************************************/
+
+#include "mm5837.h"
+
+
+//**************************************************************************
+//  CONSTEXPR DEFINITIONS
+//**************************************************************************
+
+constexpr int mm5837_device::m_frequency[];
+
+
+//**************************************************************************
+//  DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type MM5837 = &device_creator<mm5837_device>;
+
+
+//**************************************************************************
+//  LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+//  mm5837_device - constructor
+//-------------------------------------------------
+
+mm5837_device::mm5837_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+	device_t(mconfig, MM5837, "MM5837 Digital Noise Source", tag, owner, clock, "mm5837", __FILE__),
+	m_output_cb(*this),
+	m_vdd(0),
+	m_timer(nullptr),
+	m_shift(0)
+{
+}
+
+//-------------------------------------------------
+//  device_start - device-specific startup
+//-------------------------------------------------
+
+void mm5837_device::device_start()
+{
+	// resolve callbacks
+	m_output_cb.resolve_safe();
+
+	// get timer
+	m_timer = timer_alloc(0);
+
+	// register for save states
+	save_item(NAME(m_shift));
+}
+
+//-------------------------------------------------
+//  device_reset - device-specific reset
+//-------------------------------------------------
+
+void mm5837_device::device_reset()
+{
+	// initialize with something
+	m_shift = 123456;
+
+	if (m_vdd < 16)
+		m_timer->adjust(attotime::zero, 0, attotime::from_hz(m_frequency[m_vdd]));
+	else
+		throw emu_fatalerror("%s: Invalid voltage: %d\n", tag(), m_vdd);
+}
+
+//-------------------------------------------------
+//  device_timer - handle timer callbacks
+//-------------------------------------------------
+
+void mm5837_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+	int tap_14 = BIT(m_shift, 13);
+	int tap_17 = BIT(m_shift, 16);
+	int zero = (m_shift == 0) ? 1 : 0;
+
+	m_shift <<= 1;
+	m_shift |= tap_14 ^ tap_17 ^ zero;
+
+	m_output_cb(BIT(m_shift, 16));
+}
diff --git a/src/devices/sound/mm5837.h b/src/devices/sound/mm5837.h
new file mode 100644
index 0000000..f7d7b18
--- /dev/null
+++ b/src/devices/sound/mm5837.h
@@ -0,0 +1,81 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+    National Semiconductor MM5837
+
+    Digital Noise Source
+
+               ___ ___
+       VDD  1 |*  u   | 5  N/C
+       VGG  2 |       | 6  N/C
+    OUTPUT  3 |       | 7  N/C
+       VSS  4 |_______| 8  N/C
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __MM5837_H__
+#define __MM5837_H__
+
+#include "emu.h"
+
+
+//**************************************************************************
+//  INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_MM5837_ADD(_tag) \
+	MCFG_DEVICE_ADD(_tag, MM5837, 0)
+
+#define MCFG_MM5837_VDD(_voltage) \
+	mm5837_device::set_vdd_voltage(*device, _voltage);
+
+#define MCFG_MM5837_OUTPUT_CB(_devcb) \
+	devcb = &mm5837_device::set_output_callback(*device, DEVCB_##_devcb);
+
+
+//**************************************************************************
+//  TYPE DEFINITIONS
+//**************************************************************************
+
+class mm5837_device : public device_t
+{
+public:
+	// construction/destruction
+	mm5837_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+	// configuration
+	static void set_vdd_voltage(device_t &device, int voltage) { downcast<mm5837_device &>(device).m_vdd = voltage; }
+	template<class _Object> static devcb_base &set_output_callback(device_t &device, _Object object)
+		{ return downcast<mm5837_device &>(device).m_output_cb.set_callback(object); }
+
+protected:
+	// device-level overrides
+	virtual void device_start() override;
+	virtual void device_reset() override;
+	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+
+private:
+	// taken from the book 'mims circuit scrapbook, vol. 1'
+	// this is the frequency the chip runs at when given a vdd voltage of -0 to -15
+	static constexpr int m_frequency[16] = { 0, 0, 0, 0, 0, 0, 1, 2267, 8731, 16382, 23531, 32564, 38347, 40010, 37800, 33173 };
+
+	// callbacks
+	devcb_write_line m_output_cb;
+
+	// voltage (as positive number)
+	int m_vdd;
+
+	// output timer
+	emu_timer *m_timer;
+
+	// state
+	uint32_t m_shift;
+};
+
+// device type definition
+extern const device_type MM5837;
+
+#endif // __MM5837_H__
diff --git a/src/devices/sound/msm5205.cpp b/src/devices/sound/msm5205.cpp
index ee1a840..c49a4dd 100644
--- a/src/devices/sound/msm5205.cpp
+++ b/src/devices/sound/msm5205.cpp
@@ -252,6 +252,11 @@ void msm5205_device::data_w(int data)
 		m_data = (data & 0x07) << 1; /* unknown */
 }
 
+WRITE8_MEMBER(msm5205_device::data_w)
+{
+	data_w(data);
+}
+
 /*
  *    Handle a change of the selector
  */
diff --git a/src/devices/sound/msm5205.h b/src/devices/sound/msm5205.h
index edf3874..a7afa5b 100644
--- a/src/devices/sound/msm5205.h
+++ b/src/devices/sound/msm5205.h
@@ -52,12 +52,16 @@ public:
 
 	// reset signal should keep for 2cycle of VCLK
 	void reset_w(int reset);
+
 	// adpcmata is latched after vclk_interrupt callback
 	void data_w(int data);
+	DECLARE_WRITE8_MEMBER(data_w);
+
 	// VCLK slave mode option
 	// if VCLK and reset or data is changed at the same time,
 	// call vclk_w after data_w and reset_w.
 	void vclk_w(int vclk);
+
 	// option , selected pin selector
 	void playmode_w(int select);
 
diff --git a/src/devices/sound/votrax.cpp b/src/devices/sound/votrax.cpp
index 505ccd3..bde5fbd 100644
--- a/src/devices/sound/votrax.cpp
+++ b/src/devices/sound/votrax.cpp
@@ -1,56 +1,41 @@
 // license:BSD-3-Clause
-// copyright-holders:Aaron Giles
+// copyright-holders:Olivier Galibert
 /***************************************************************************
 
     votrax.c
 
-    Simple VOTRAX SC-01 simulator based on sample fragments.
+    Votrax SC01A simulation
 
 ***************************************************************************/
 
-#include "emu.h"
-#include "votrax.h"
-
-
-//**************************************************************************
-//  DEBUGGING
-//**************************************************************************
-
-#define TEMP_HACKS      (1)
-
-#define LOG_TIMING      (0)
-#define LOG_LOWPARAM    (0)
-#define LOG_GLOTTAL     (0)
-#define LOG_TRANSITION  (0)
-
-
-
-//**************************************************************************
-//  CONSTANTS
-//**************************************************************************
+/*
+  tp3 stb i1 i2 tp2
+  1   1   o  o  white noise
+  1   0   -  1  phone timing clock
+  1   0   1  0  closure tick
+  1   0   0  0  sram write pulse
+  0   -   -  -  sram write pulse
 
-// note that according to the patent timing circuit, p1/p2 and phi1/phi2
-// run 4x faster than all references in the patent text
-const uint32_t P_CLOCK_BIT = 5;       // 5 according to timing diagram
-const uint32_t PHI_CLOCK_BIT = 3;     // 3 according to timing diagram
+i1.o = glottal impulse
+i2.o = white noise
 
+tp1 = phi clock (tied to f2q rom access)
+*/
 
+#include "emu.h"
+#include "votrax.h"
 
-//**************************************************************************
-//  GLOBAL VARIABLES
-//**************************************************************************
 
-// device type definition
 const device_type VOTRAX_SC01 = &device_creator<votrax_sc01_device>;
 
-// ROM definition for the Votrax phoneme ROM
+// ROM definition for the Votrax phone ROM
 ROM_START( votrax_sc01 )
-	ROM_REGION( 0x200, "phoneme", 0 )
-	ROM_LOAD( "sc01.bin", 0x0000, 0x200, CRC(0353dd6c) SHA1(00e8e497b96a10bd9f4d7e559433c3c209b0d3a8) )
+	ROM_REGION64_LE( 0x200, "internal", 0 )
+	ROM_LOAD( "sc01a.bin", 0x000, 0x200, CRC(fc416227) SHA1(1d6da90b1807a01b5e186ef08476119a862b5e6d) )
 ROM_END
 
-// textual phoneme names for debugging
-const char *const votrax_sc01_device::s_phoneme_table[64] =
+// textual phone names for debugging
+const char *const votrax_sc01_device::s_phone_table[64] =
 {
 	"EH3",  "EH2",  "EH1",  "PA0",  "DT",   "A1",   "A2",   "ZH",
 	"AH2",  "I3",   "I2",   "I1",   "M",    "N",    "B",    "V",
@@ -62,82 +47,65 @@ const char *const votrax_sc01_device::s_phoneme_table[64] =
 	"THV",  "TH",   "ER",   "EH",   "E1",   "AW",   "PA1",  "STOP"
 };
 
-// this waveform is derived from measuring fig. 10 in the patent
-// it is only an approximation
-const double votrax_sc01_device::s_glottal_wave[16] =
+// This waveform is built using a series of transistors as a resistor
+// ladder.  There is first a transistor to ground, then a series of
+// seven transistors one quarter the size of the first one, then it
+// finishes by an active resistor to +9V.
+//
+// The terminal of the transistor to ground is used as a middle value.
+// Index 0 is at that value. Index 1 is at 0V.  Index 2 to 8 start at
+// just after the resistor down the latter.  Indices 9+ are the middle
+// value again.
+//
+// For simplicity, we rescale the values to get the middle at 0 and
+// the top at 1.  The final wave is very similar to the patent
+// drawing.
+
+const double votrax_sc01_device::s_glottal_wave[9] =
 {
 	0,
-	16.0/22.0,
-	-22.0/22.0,
-	-17.0/22.0,
-	-15.0/22.0,
-	-10.0/22.0,
-	-7.0/22.0,
-	-4.0/22.0,
-	0,
-	0,
-	0,
-	0,
-	0,
-	0,
-	0,
-	0
+	-4/7.0,
+	7/7.0,
+	6/7.0,
+	5/7.0,
+	4/7.0,
+	3/7.0,
+	2/7.0,
+	1/7.0
 };
 
 
-
-//**************************************************************************
-//  LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-//  votrax_sc01_device - constructor
-//-------------------------------------------------
-
 votrax_sc01_device::votrax_sc01_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
 	: device_t(mconfig, VOTRAX_SC01, "Votrax SC-01", tag, owner, clock, "votrax", __FILE__),
-		device_sound_interface(mconfig, *this),
-		m_stream(nullptr),
-		m_phoneme_timer(nullptr), m_rom(nullptr), m_inflection(0), m_phoneme(0),
-		m_request_cb(*this), m_request_state(0), m_internal_request(0), m_master_clock_freq(0), m_master_clock(0), m_counter_34(0),
-		m_latch_70(0), m_latch_72(0), m_beta1(0), m_p2(0), m_p1(0), m_phi2(0), m_phi1(0), m_phi2_20(0), m_phi1_20(0), m_subphoneme_period(0),
-		m_subphoneme_count(0), m_clock_88(0), m_latch_42(0), m_counter_84(0), m_latch_92(0), m_srff_132(false), m_srff_114(false), m_srff_112(false),
-		m_srff_142(false), m_latch_80(0), m_counter_220(0), m_counter_222(0), m_counter_224(0), m_counter_234(0), m_counter_236(0), m_fgate(0),
-		m_glottal_sync(0), m_0625_clock(0), m_counter_46(0), m_latch_46(0), m_latch_168(0), m_latch_170(0), m_f1(0), m_f2(0), m_fc(0), m_f3(0),
-		m_f2q(0), m_va(0), m_fa(0), m_noise_clock(0), m_shift_252(0), m_counter_250(0)
+	  device_sound_interface(mconfig, *this),
+	  m_stream(nullptr),
+	  m_rom(*this, "internal"),
+	  m_ar_cb(*this)
 {
 }
 
-//**************************************************************************
-//  READ/WRITE HANDLERS
-//**************************************************************************
-
-//-------------------------------------------------
-//  write - handle a write to the control register
-//-------------------------------------------------
-
 WRITE8_MEMBER( votrax_sc01_device::write )
 {
 	// flush out anything currently processing
 	m_stream->update();
 
+	u8 prev = m_phone;
+
 	// only 6 bits matter
-	m_phoneme = data & 0x3f;
-const uint8_t *rom = m_rom + (m_phoneme << 3);
-osd_printf_debug("%s: STROBE %s (F1=%X F2=%X FC=%X F3=%X F2Q=%X VA=%X FA=%X CL=%X CLD=%X VD=%X PAC=%X PH=%02X)\n",
-		machine().time().as_string(3), s_phoneme_table[m_phoneme],
-		rom[0] >> 4, rom[1] >> 4, rom[2] >> 4, rom[3] >> 4, rom[4] >> 4, rom[5] >> 4, rom[6] >> 4,
-		rom[3] & 0xf, rom[4] & 0xf, rom[5] & 0xf, rom[6] & 0xf, rom[7]);
-
-	// the STROBE signal resets the phoneme counter
-	m_counter_84 = 0xf;
-
-	// not in the schematics, but necessary to fully reset the request latch
-	m_latch_92 = 0;
-
-	// clear the request signal
-	m_request_cb(m_request_state = m_internal_request = CLEAR_LINE);
-	m_phoneme_timer->adjust(attotime::zero);
+	m_phone = data & 0x3f;
+
+	if(m_phone != prev || m_phone != 0x3f)
+		logerror("phone %02x.%d %s\n", m_phone, m_inflection, s_phone_table[m_phone]);
+
+	m_ar_state = CLEAR_LINE;
+
+	// Schedule a commit/ar reset at roughly 0.1ms in the future (one
+	// phi1 transition followed by the rom extra state in practice),
+	// but only if there isn't already one on the fly.  It will
+	// override an end-of-phone timeout if there's one pending, but
+	// that's not a problem since stb does that anyway.
+	if(m_timer->expire().is_never() || m_timer->param() != T_COMMIT_PHONE)
+		m_timer->adjust(attotime::from_ticks(72, m_mainclock), T_COMMIT_PHONE);
 }
 
 
@@ -150,134 +118,518 @@ WRITE8_MEMBER( votrax_sc01_device::inflection_w )
 {
 	// only 2 bits matter
 	data &= 3;
-	if (m_inflection == data)
+	if(m_inflection == data)
 		return;
 
-	// append an inflection marker
 	m_stream->update();
 	m_inflection = data;
 }
 
 
+//-------------------------------------------------
+//  sound_stream_update - handle update requests
+//  for our sound stream
+//-------------------------------------------------
+
+void votrax_sc01_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
+{
+	for(int i=0; i<samples; i++) {
+		m_sample_count++;
+		if(m_sample_count & 1)
+			chip_update();
+		outputs[0][i] = analog_calc();
+	}
+}
+
+
 
 //**************************************************************************
-//  CORE LOGIC
+//  DEVICE INTERFACE
 //**************************************************************************
 
 //-------------------------------------------------
-//  update_subphoneme_clock_period - re-compute the
-//  period of the sub-phoneme clock, as a multiple
-//  of the master clock
+//  rom_region - return a pointer to the device's
+//  internal ROM region
 //-------------------------------------------------
 
-void votrax_sc01_device::update_subphoneme_clock_period()
+const tiny_rom_entry *votrax_sc01_device::device_rom_region() const
 {
-	assert(m_latch_80 < 128);
+	return ROM_NAME( votrax_sc01 );
+}
 
-/*
-    The sub-phoneme timing circuit is based off the switching capacitor
-    technique described in the Votrax patent. Replacing the capacitor
-    ladder with [Rx] representing the effective resistance, the circuit
-    becomes essentially a pair of op-amps:
-
-         VM
-         | i1
-        [R1]
-         |                       Vc
-         +----------------------+
-         |        +---|C1|---+  |
-        [R2]      |          |  |  |\
-         |Vb i2   |    |\    |  +--++\
-         +--[Rx]--+----+-\   |     |  >
-         |             |  >--+-----+-/
-        [R3]      +----++/   Vc    |/
-         |i3      |    |/
-         +--------+ Va
-         |
-        [R4]
-         |
-         0
-
-    We have two op-amps, the left used as a standard amplifier, the right
-    one as a comparator.  The circuit triggers when the two inputs of the
-    right op-amp are equal.
-
-    The left part of the circuit (before C1) is simply a current injector.
-    It's all made of resistors, there's no modulated input, so everything
-    is going to be constant.  If you don't know about op-amps used as
-    amplifiers, you just need to know that it forces its two inputs to
-    have the same voltage while not sending or providing any current
-    through there (only though its output in fact).
-
-    In the schema, the injected current is i2.  Basic equations apply:
-      Va = R4.i3
-      Vb = Va + R3.i3
-      Vb = Va + Rx.i2
-      Vc = Vb + R2.i1
-      VM = Vc + R1.i1
-      i1 = i2 + i3
-
-    And the tipping happens when the voltage on the right of C1 reaches
-    Vc, so:
-      Vc = Va + i2.T/C1
-
-    (i2 being a constant, the integration is kinda easy)
-
-    Some maths later:
-      R3.i3 = Rx.i2 -> i3 = Rx/R3.i2
-      i1 = (1+Rx/R3).i2
-      Va + (Rx + R2 + R2.Rx/R3).i2 = Va + T/C1.i2
-      T = C1*(Rx*(1+R2/R3) + R2)
-
-    Which isn't, interestingly though not surprisingly, dependant on Vm,
-    R1 or R4.  And you have to round it to the next multiple of
-    0.2ms+0.1ms due to the clocking on p2 and its offset to p1 (charging
-    only happens on p1 active), and add one p1/p2 cycle (0.2ms) for the
-    discharge.
-
-    So now you have your base clock, which you have to multiply by 16 to
-    get the phoneme length.
-
-    r2 = 9e3
-    r3 = 1e3
-    c1 = 1000e-12
-    rx = 1/(5KHz * cx)
-*/
 
-	// determine total capacitance
-	double cx = 0;
-	if ((m_latch_80 & 0x01) != 0) cx += 5e-12;
-	if ((m_latch_80 & 0x02) != 0) cx += 11e-12;
-	if ((m_latch_80 & 0x04) != 0) cx += 21e-12;
-	if ((m_latch_80 & 0x08) != 0) cx += 43e-12;
-	if ((m_latch_80 & 0x10) != 0) cx += 86e-12;
-	if ((m_latch_80 & 0x20) != 0) cx += 173e-12;
-	if ((m_latch_80 & 0x40) != 0) cx += 345e-12;
-
-	// apply the equation above to determine charging time
-	// note that the 5kHz listed above for P1 is for a nominal master
-	// clock frequency of 1.28MHz, meaning it is master clock / 128
-	// which should be the P1 clock but appears to be a bit different
-	double p1_frequency = double(m_master_clock_freq) / double(1 << (P_CLOCK_BIT + 2));
-	double rx = 1.0 / (p1_frequency * cx);
-	double period = 1000e-12 * (rx * (1.0 + 9e3 / 1e3) + 9e3);
-
-	// convert to master clock cycles and round up
-	m_subphoneme_period = uint32_t(ceil(period * double(m_master_clock_freq)));
+//-------------------------------------------------
+//  device_start - handle device startup
+//-------------------------------------------------
+
+void votrax_sc01_device::device_start()
+{
+	// initialize internal state
+	m_mainclock = clock();
+	m_sclock = m_mainclock / 18.0;
+	m_cclock = m_mainclock / 36.0;
+	m_stream = stream_alloc(0, 1, m_sclock);
+	m_timer = timer_alloc();
+
+	// reset outputs
+	m_ar_cb.resolve_safe();
+	m_ar_state = ASSERT_LINE;
+
+	// save inputs
+	save_item(NAME(m_inflection));
+	save_item(NAME(m_phone));
+
+	// save outputs
+	save_item(NAME(m_ar_state));
+
+	// save internal state
+	save_item(NAME(m_rom_duration));
+	save_item(NAME(m_rom_vd));
+	save_item(NAME(m_rom_cld));
+	save_item(NAME(m_rom_fa));
+	save_item(NAME(m_rom_fc));
+	save_item(NAME(m_rom_va));
+	save_item(NAME(m_rom_f1));
+	save_item(NAME(m_rom_f2));
+	save_item(NAME(m_rom_f2q));
+	save_item(NAME(m_rom_f3));
+	save_item(NAME(m_rom_closure));
+	save_item(NAME(m_rom_pause));
+	save_item(NAME(m_cur_fa));
+	save_item(NAME(m_cur_fc));
+	save_item(NAME(m_cur_va));
+	save_item(NAME(m_cur_f1));
+	save_item(NAME(m_cur_f2));
+	save_item(NAME(m_cur_f2q));
+	save_item(NAME(m_cur_f3));
+	save_item(NAME(m_filt_fa));
+	save_item(NAME(m_filt_fc));
+	save_item(NAME(m_filt_va));
+	save_item(NAME(m_filt_f1));
+	save_item(NAME(m_filt_f2));
+	save_item(NAME(m_filt_f2q));
+	save_item(NAME(m_filt_f3));
+	save_item(NAME(m_phonetick));
+	save_item(NAME(m_ticks));
+	save_item(NAME(m_pitch));
+	save_item(NAME(m_closure));
+	save_item(NAME(m_update_counter));
+	save_item(NAME(m_cur_closure));
+	save_item(NAME(m_noise));
+	save_item(NAME(m_cur_noise));
+	save_item(NAME(m_voice_1));
+	save_item(NAME(m_voice_2));
+	save_item(NAME(m_voice_3));
+	save_item(NAME(m_noise_1));
+	save_item(NAME(m_noise_2));
+	save_item(NAME(m_noise_3));
+	save_item(NAME(m_noise_4));
+	save_item(NAME(m_vn_1));
+	save_item(NAME(m_vn_2));
+	save_item(NAME(m_vn_3));
+	save_item(NAME(m_vn_4));
+	save_item(NAME(m_vn_5));
+	save_item(NAME(m_vn_6));
+	save_item(NAME(m_f1_a));
+	save_item(NAME(m_f1_b));
+	save_item(NAME(m_f2v_a));
+	save_item(NAME(m_f2v_b));
+	save_item(NAME(m_f2n_a));
+	save_item(NAME(m_f2n_b));
+	save_item(NAME(m_f3_a));
+	save_item(NAME(m_f3_b));
+	save_item(NAME(m_f4_a));
+	save_item(NAME(m_f4_b));
+	save_item(NAME(m_fx_a));
+	save_item(NAME(m_fx_b));
+	save_item(NAME(m_fn_a));
+	save_item(NAME(m_fn_b));
+}
+
+
+//-------------------------------------------------
+//  device_reset - handle device reset
+//-------------------------------------------------
+
+void votrax_sc01_device::device_reset()
+{
+	// Technically, there's no reset in this chip, and initial state
+	// is random.  Still, it's a good idea to start it with something
+	// sane.
+
+	m_phone = 0x3f;
+	m_inflection = 0;
+	m_ar_state = ASSERT_LINE;
+	m_ar_cb(m_ar_state);
+
+	m_sample_count = 0;
+
+	// Initialize the m_rom* values
+	phone_commit();
+
+	// Clear the interpolation sram
+	m_cur_fa = m_cur_fc = m_cur_va = 0;
+	m_cur_f1 = m_cur_f2 = m_cur_f2q = m_cur_f3 = 0;
+
+	// Initialize the m_filt* values and the filter coefficients
+	filters_commit(true);
+
+	// Clear the rest of the internal digital state
+	m_pitch = 0;
+	m_closure = 0;
+	m_update_counter = 0;
+	m_cur_closure = true;
+	m_noise = 0;
+	m_cur_noise = false;
+
+	// Clear the analog level histories
+	memset(m_voice_1, 0, sizeof(m_voice_1));
+	memset(m_voice_2, 0, sizeof(m_voice_2));
+	memset(m_voice_3, 0, sizeof(m_voice_3));
+
+	memset(m_noise_1, 0, sizeof(m_noise_1));
+	memset(m_noise_2, 0, sizeof(m_noise_2));
+	memset(m_noise_3, 0, sizeof(m_noise_3));
+	memset(m_noise_4, 0, sizeof(m_noise_4));
+
+	memset(m_vn_1, 0, sizeof(m_vn_1));
+	memset(m_vn_2, 0, sizeof(m_vn_2));
+	memset(m_vn_3, 0, sizeof(m_vn_3));
+	memset(m_vn_4, 0, sizeof(m_vn_4));
+	memset(m_vn_5, 0, sizeof(m_vn_5));
+	memset(m_vn_6, 0, sizeof(m_vn_6));
+}
+
+
+//-------------------------------------------------
+//  device_clock_changed - handle dynamic clock
+//  changes by altering our output frequency
+//-------------------------------------------------
+
+void votrax_sc01_device::device_clock_changed()
+{
+	// lookup the new frequency of the master clock, and update if changed
+	u32 newfreq = clock();
+	if(newfreq != m_mainclock) {
+		m_stream->update();
+
+		if(!m_timer->expire().is_never()) {
+			// determine how many clock ticks remained on the timer
+			u64 remaining = m_timer->remaining().as_ticks(m_mainclock);
+
+			// adjust the timer to the same number of ticks based on the new frequency
+			m_timer->adjust(attotime::from_ticks(remaining, newfreq));
+		}
+		m_mainclock = newfreq;
+		m_sclock = m_mainclock / 18.0;
+		m_cclock = m_mainclock / 36.0;
+		m_stream->set_sample_rate(m_sclock);
+		filters_commit(true);
+	}
 }
 
+
 //-------------------------------------------------
-//  bits_to_caps - compute the final capacity from
-//  a grid of bit-selected caps
+//  device_timer - handle device timer
 //-------------------------------------------------
 
-double votrax_sc01_device::bits_to_caps(uint32_t value, int caps_count, const double *caps_values)
+void votrax_sc01_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
 {
-	double sum = 0;
-	for(int i=0; i<caps_count; i++)
-		if(value & (1<<i))
-			sum += caps_values[i];
-	return sum;
+	m_stream->update();
+
+	switch(param) {
+	case T_COMMIT_PHONE:
+		// strobe -> commit transition,
+		phone_commit();
+		m_timer->adjust(attotime::from_ticks(16*(m_rom_duration*4+1)*4*9+2, m_mainclock), T_END_OF_PHONE);
+		break;
+
+	case T_END_OF_PHONE:
+		// end of phone
+		m_ar_state = ASSERT_LINE;
+		break;
+	}
+
+	m_ar_cb(m_ar_state);
+}
+
+void votrax_sc01_device::phone_commit()
+{
+	// Only these two counters are reset on phone change, the rest is
+	// free-running.
+	m_phonetick = 0;
+	m_ticks = 0;
+
+	// In the real chip, the rom is re-read all the time.  Since it's
+	// internal and immutable, no point in not caching it though.
+	for(int i=0; i<64; i++) {
+		u64 val = reinterpret_cast<const u64 *>(m_rom->base())[i];
+		if(m_phone == ((val >> 56) & 0x3f)) {
+			m_rom_f1  = bitswap(val,  0,  7, 14, 21);
+			m_rom_va  = bitswap(val,  1,  8, 15, 22);
+			m_rom_f2  = bitswap(val,  2,  9, 16, 23);
+			m_rom_fc  = bitswap(val,  3, 10, 17, 24);
+			m_rom_f2q = bitswap(val,  4, 11, 18, 25);
+			m_rom_f3  = bitswap(val,  5, 12, 19, 26);
+			m_rom_fa  = bitswap(val,  6, 13, 20, 27);
+
+			// These two values have their bit orders inverted
+			// compared to everything else due to a bug in the
+			// prototype (miswiring of the comparator with the ticks
+			// count) they compensated in the rom.
+
+			m_rom_cld = bitswap(val, 34, 32, 30, 28);
+			m_rom_vd  = bitswap(val, 35, 33, 31, 29);
+
+			m_rom_closure  = bitswap(val, 36);
+			m_rom_duration = bitswap(~val, 37, 38, 39, 40, 41, 42, 43);
+
+			// Hard-wired on the die, not an actual part of the rom.
+			m_rom_pause = (m_phone == 0x03) || (m_phone == 0x3e);
+
+			if(0)
+				logerror("commit fa=%x va=%x fc=%x f1=%x f2=%x f2q=%x f3=%x dur=%02x cld=%x vd=%d cl=%d pause=%d\n", m_rom_fa, m_rom_va, m_rom_fc, m_rom_f1, m_rom_f2, m_rom_f2q, m_rom_f3, m_rom_duration, m_rom_cld, m_rom_vd, m_rom_closure, m_rom_pause);
+
+			// That does not happen in the sc01(a) rom, but let's
+			// cover our behind.
+			if(m_rom_cld == 0)
+				m_cur_closure = m_rom_closure;
+
+			return;
+		}
+	}
+}
+
+void votrax_sc01_device::interpolate(u8 &reg, u8 target)
+{
+	// One step of interpolation, adds one eight of the distance
+	// between the current value and the target.
+	reg = reg - (reg >> 3) + (target << 1);
+}
+
+void votrax_sc01_device::chip_update()
+{
+	// Phone tick counter update.  Stopped when ticks reach 16.
+	// Technically the counter keeps updating, but the comparator is
+	// disabled.
+	if(m_ticks != 0x10) {
+		m_phonetick++;
+		// Comparator is with duration << 2, but there's a one-tick
+		// delay in the path.
+		if(m_phonetick == ((m_rom_duration << 2) | 1)) {
+			m_phonetick = 0;
+			m_ticks++;
+			if(m_ticks == m_rom_cld)
+				m_cur_closure = m_rom_closure;
+		}
+	}
+
+	// The two update timing counters.  One divides by 16, the other
+	// by 48, and they're phased so that the 208Hz counter ticks
+	// exactly between two 625Hz ticks.
+	m_update_counter++;
+	if(m_update_counter == 0x30)
+		m_update_counter = 0;
+
+	bool tick_625 = !(m_update_counter & 0xf);
+	bool tick_208 = m_update_counter == 0x28;
+
+	// Formant update.  Die bug there: fc should be updated, not va.
+	// The formants are frozen on a pause phone unless both voice and
+	// noise volumes are zero.
+	if(tick_208 && (!m_rom_pause || !(m_filt_fa || m_filt_va))) {
+		//      interpolate(m_cur_va,  m_rom_va);
+		interpolate(m_cur_fc,  m_rom_fc);
+		interpolate(m_cur_f1,  m_rom_f1);
+		interpolate(m_cur_f2,  m_rom_f2);
+		interpolate(m_cur_f2q, m_rom_f2q);
+		interpolate(m_cur_f3,  m_rom_f3);
+		//      logerror("int fa=%x va=%x fc=%x f1=%x f2=%02x f2q=%02x f3=%x\n", m_cur_fa >> 4, m_cur_va >> 4, m_cur_fc >> 4, m_cur_f1 >> 4, m_cur_f2 >> 3, m_cur_f2q >> 4, m_cur_f3 >> 4);
+	}
+
+	// Non-formant update. Same bug there, va should be updated, not fc.
+	if(tick_625) {
+		if(m_ticks >= m_rom_vd)
+			interpolate(m_cur_fa, m_rom_fa);
+		if(m_ticks >= m_rom_cld)
+			//          interpolate(m_cur_fc, m_rom_fc);
+			interpolate(m_cur_va, m_rom_va);
+		//      logerror("int fa=%x va=%x fc=%x f1=%x f2=%02x f2q=%02x f3=%x\n", m_cur_fa >> 4, m_cur_va >> 4, m_cur_fc >> 4, m_cur_f1 >> 4, m_cur_f2 >> 3, m_cur_f2q >> 4, m_cur_f3 >> 4);
+	}
+
+	// Closure counter, reset every other tick in theory when not
+	// active (on the extra rom cycle).
+	//
+	// The closure level is immediatly used in the analog path,
+	// there's no pitch synchronization.
+
+	if(!m_cur_closure && (m_filt_fa || m_filt_va))
+		m_closure = 0;
+	else if(m_closure != 7 << 2)
+		m_closure ++;
+
+	// Pitch counter.  Equality comparison, so it's possible to make
+	// it miss by manipulating the inflection inputs, but it'll wrap.
+	// There's a delay, hence the +1.
+	m_pitch = (m_pitch + 1) & 0x7f;
+	if(m_pitch == (0x7f ^ (m_inflection << 4) ^ m_filt_f1) + 1)
+		m_pitch = 0;
+
+	// Filters are updated in index 1 of the pitch wave, which does
+	// indeed mean four times in a row.
+	if((m_pitch >> 2) == 1)
+		filters_commit(false);
+
+	// Noise shift register.  15 bits, with a nxor on the last two
+	// bits for the loop.
+	bool inp = (1||m_filt_fa) && m_cur_noise && (m_noise != 0x7fff);
+	m_noise = ((m_noise << 1) & 0x7ffe) | inp;
+	m_cur_noise = !(((m_noise >> 14) ^ (m_noise >> 13)) & 1);
+
+	//  logerror("tick %02x.%03x 625=%d 208=%d pitch=%02x.%x ns=%04x ni=%d noise=%d cl=%x.%x clf=%d/%d\n", m_ticks, m_phonetick, tick_625, tick_208, m_pitch >> 2, m_pitch & 3, m_noise, inp, m_cur_noise, m_closure >> 2, m_closure & 3, m_rom_closure, m_cur_closure);
+}
+
+void votrax_sc01_device::filters_commit(bool force)
+{
+	m_filt_fa = m_cur_fa >> 4;
+	m_filt_fc = m_cur_fc >> 4;
+	m_filt_va = m_cur_va >> 4;
+
+	if(force || m_filt_f1 != m_cur_f1 >> 4) {
+		m_filt_f1 = m_cur_f1 >> 4;
+
+		build_standard_filter(m_f1_a, m_f1_b,
+							  11247,
+							  11797,
+							  949,
+							  52067,
+							  2280 + bits_to_caps(m_filt_f1, { 2546, 4973, 9861, 19724 }),
+							  166272);
+	}
+
+	if(force || m_filt_f2 != m_cur_f2 >> 3 || m_filt_f2q != m_cur_f2q >> 4) {
+		m_filt_f2 = m_cur_f2 >> 3;
+		m_filt_f2q = m_cur_f2q >> 4;
+
+		build_standard_filter(m_f2v_a, m_f2v_b,
+							  24840,
+							  29154,
+							  829 + bits_to_caps(m_filt_f2q, { 1390, 2965, 5875, 11297 }),
+							  38180,
+							  2352 + bits_to_caps(m_filt_f2, { 833, 1663, 3164, 6327, 12654 }),
+							  34270);
+
+		build_injection_filter(m_f2n_a, m_f2n_b,
+							   29154,
+							   829 + bits_to_caps(m_filt_f2q, { 1390, 2965, 5875, 11297 }),
+							   38180,
+							   2352 + bits_to_caps(m_filt_f2, { 833, 1663, 3164, 6327, 12654 }),
+							   34270);
+	}
+
+	if(force || m_filt_f3 != m_cur_f3 >> 4) {
+		m_filt_f3 = m_cur_f3 >> 4;
+		build_standard_filter(m_f3_a, m_f3_b,
+							  0,
+							  17594,
+							  868,
+							  18828,
+							  8480 + bits_to_caps(m_filt_f3, { 2226, 4485, 9056, 18111 }),
+							  50019);
+	}
+
+	if(force) {
+		build_standard_filter(m_f4_a, m_f4_b,
+							  0,
+							  28810,
+							  1165,
+							  21457,
+							  8558,
+							  7289);
+
+		build_lowpass_filter(m_fx_a, m_fx_b,
+							 1122,
+							 23131);
+
+		build_noise_shaper_filter(m_fn_a, m_fn_b,
+								  15500,
+								  14854,
+								  8450,
+								  9523,
+								  14083);
+	}
+
+	if(0)
+		if(m_filt_fa || m_filt_va || m_filt_fc || m_filt_f1 || m_filt_f2 || m_filt_f2q || m_filt_f3)
+			logerror("filter fa=%x va=%x fc=%x f1=%x f2=%02x f2q=%x f3=%x\n",
+					 m_filt_fa, m_filt_va, m_filt_fc, m_filt_f1, m_filt_f2, m_filt_f2q, m_filt_f3);
+}
+
+stream_sample_t votrax_sc01_device::analog_calc()
+{
+	// Voice-only path.
+	// 1. Pick up the pitch wave
+
+	double v = m_pitch >= (9 << 2) ? 0 : s_glottal_wave[m_pitch >> 2];
+
+	// 2. Multiply by the initial amplifier.  It's linear on the die,
+	// even if it's not in the patent.
+	v = v * m_filt_va / 15.0;
+	shift_hist(v, m_voice_1);
+
+	// 3. Apply the f1 filter
+	v = apply_filter(m_voice_1, m_voice_2, m_f1_a, m_f1_b);
+	shift_hist(v, m_voice_2);
+
+	// 4. Apply the f2 filter, voice half
+	v = apply_filter(m_voice_2, m_voice_3, m_f2v_a, m_f2v_b);
+	shift_hist(v, m_voice_3);
+
+	// Noise-only path
+	// 5. Pick up the noise pitch.  Amplitude is linear.  Base
+	// intensity should be checked w.r.t the voice.
+	double n = 1e4 * ((m_pitch & 0x40 ? m_cur_noise : false) ? 1 : -1);
+	n = n * m_filt_fa / 15.0;
+	shift_hist(n, m_noise_1);
+
+	// 6. Apply the noise shaper
+	n = apply_filter(m_noise_1, m_noise_2, m_fn_a, m_fn_b);
+	shift_hist(n, m_noise_2);
+
+	// 7. Scale with the f2 noise input
+	double n2 = n * m_filt_fc / 15.0;
+	shift_hist(n2, m_noise_3);
+
+	// 8. Apply the f2 filter, noise half,
+	n2 = apply_filter(m_noise_3, m_noise_4, m_f2n_a, m_f2n_b);
+	shift_hist(n2, m_noise_4);
+
+	// Mixed path
+	// 9. Add the f2 voice and f2 noise outputs
+	double vn = v + n2;
+	shift_hist(vn, m_vn_1);
+
+	// 10. Apply the f3 filter
+	vn = apply_filter(m_vn_1, m_vn_2, m_f3_a, m_f3_b);
+	shift_hist(vn, m_vn_2);
+
+	// 11. Second noise insertion
+	vn += n * (5 + (15^m_filt_fc))/20.0;
+	shift_hist(vn, m_vn_3);
+
+	// 12. Apply the f4 filter
+	vn = apply_filter(m_vn_3, m_vn_4, m_f4_a, m_f4_b);
+	shift_hist(vn, m_vn_4);
+
+	// 13. Apply the glottal closure amplitude, also linear
+	vn = vn * (7 ^ (m_cur_closure >> 2)) / 7.0;
+	shift_hist(vn, m_vn_5);
+
+	// 13. Apply the final fixed filter
+	vn = apply_filter(m_vn_5, m_vn_6, m_fx_a, m_fx_b);
+	shift_hist(vn, m_vn_6);
+
+	return int(vn*50000);
 }
 
 /*
@@ -301,6 +653,8 @@ double votrax_sc01_device::bits_to_caps(uint32_t value, int caps_count, const do
   |                            V2^   \++-0
   |                                   \|
 
+  It happens to be what most of the filters in the sc01a look like.
+
   You need to determine the transfer function H(s) of the circuit, which is
   defined as the ratio Vo/Vi.  To do that, you use some properties:
 
@@ -437,24 +791,56 @@ double votrax_sc01_device::bits_to_caps(uint32_t value, int caps_count, const do
   - apply the now non-amplifying filter to the historized amplified
     input
 
-  That way reduces the probability of the output boucing all over the
+  That way reduces the probability of the output bouncing all over the
   place.
 
+  Except, we're not done yet.  Doing resistors precisely in an IC is
+  very hard and/or expensive (you may have heard of "laser cut
+  resistors" in DACs of the time).  Doing capacitors is easier, and
+  their value is proportional to their surface.  So there are no
+  resistors on the sc01 die (which is a lie, there are three, but not
+  in the filter path.  They are used to scale the voltage in the pitch
+  wave and to generate +5V from the +9V), but a magic thing called a
+  switched capacitor.  Lookup patent 4,433,210 for details.  Using
+  high frequency switching a capacitor can be turned into a resistor
+  of value 1/(C*f) where f is the switching frequency (20Khz,
+  main/36).  And the circuit is such that the absolute value of the
+  capacitors is irrelevant, only their ratio is useful, which factors
+  out the intrinsic capacity-per-surface-area of the IC which may be
+  hard to keep stable from one die to another.  As a result all the
+  capacitor values we use are actually surfaces in square micrometers.
+
+  For the curious, it looks like the actual capacitance was around 25
+  femtofarad per square micrometer.
+
 */
 
+void votrax_sc01_device::build_standard_filter(double *a, double *b,
+											   double c1t, // Unswitched cap, input, top
+											   double c1b, // Switched cap, input, bottom
+											   double c2t, // Unswitched cap, over first amp-op, top
+											   double c2b, // Switched cap, over first amp-op, bottom
+											   double c3,  // Cap between the two op-amps
+											   double c4)  // Cap over second op-amp
+{
+	// First compute the three coefficients of H(s).  One can note
+	// that there is as many capacitor values on both sides of the
+	// division, which confirms that the capacity-per-surface-area
+	// is not needed.
+	double k0 = c1t / (m_cclock * c1b);
+	double k1 = c4 * c2t / (m_cclock * c1b * c3);
+	double k2 = c4 * c2b / (m_cclock * m_cclock * c1b * c3);
 
-//-------------------------------------------------------------
-//  filter_s_to_z - analog to digital filter transformation
-//-------------------------------------------------------------
+	// Estimate the filter cutoff frequency
+	double fpeak = sqrt(fabs(k0*k1 - k2))/(2*M_PI*k2);
 
-void votrax_sc01_device::filter_s_to_z(const double *k, double fs, double *a, double *b)
-{
-	double fpeak = sqrt(fabs(k[0]*k[1]-k[2]))/(2*M_PI*k[2]);
-	double zc = 2*M_PI*fpeak/tan(M_PI*fpeak/fs);
+	// Turn that into a warp multiplier
+	double zc = 2*M_PI*fpeak/tan(M_PI*fpeak / m_sclock);
 
-	double m0 = zc*k[0];
-	double m1 = zc*k[1];
-	double m2 = zc*zc*k[2];
+	// Finally compute the result of the z-transform
+	double m0 = zc*k0;
+	double m1 = zc*k1;
+	double m2 = zc*zc*k2;
 
 	a[0] = 1+m0;
 	a[1] = 3+m0;
@@ -466,912 +852,154 @@ void votrax_sc01_device::filter_s_to_z(const double *k, double fs, double *a, do
 	b[3] = 1-m1+m2;
 }
 
+/*
+  Second filter type used once at the end, much simpler:
 
-//-------------------------------------------------------------
-//  apply_filter - apply the digital filter (before output
-//                 shifting, so y[0] is one step in the past)
-//-------------------------------------------------------------
-double votrax_sc01_device::apply_filter(const double *x, const double *y, const double *a, const double *b)
-{
-	return (x[0]*a[0] + x[1]*a[1] + x[2]*a[2] + x[3]*a[3] - y[0]*b[1] - y[1]*b[2] - y[2]*b[3]) / b[0];
-}
-
+  |           +--[R1]--+
+  |           |        |
+  |           +--|C1|--+
+  |           |        |
+  |  Vi       |  |\    |
+  |  ---[R0]--+--+-\   |
+  |              |  >--+------ Vo
+  |            0-++/
+  |              |/
 
-//-------------------------------------------------------------
-//  shift_hist - shift a value in an output history
-//-------------------------------------------------------------
 
-void votrax_sc01_device::shift_hist(double val, double *hist_array, int hist_size)
-{
-	for(int i = 0; i < hist_size-1; i++)
-		hist_array[hist_size-1-i] = hist_array[hist_size-2-i];
-	hist_array[0] = val;
-}
-
-
-//-------------------------------------------------
-//  sound_stream_update - handle update requests
-//  for our sound stream
-//-------------------------------------------------
+  Vi/R0 = Vo / (1/(1/R1 + s.C1)) = Vo (1/R1 + s.C1)
+  H(s) = Vo/Vi = (R1/R0) * (1 / (1 + s.R1.C1))
+*/
 
-void votrax_sc01_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
-{
-	// determine how many master half-clocks per sample
-	int half_clocks_per_sample = (m_master_clock_freq * 2) / stream.sample_rate();
-
-	// iterate over clocks (samples)
-	stream_sample_t *dest = outputs[0];
-	while (samples--)
-	{
-		// run the digital logic at the master clock rate
-		double glottal_out = 0;
-		uint8_t noise_out_digital = 0;
-		for (int curclock = 0; curclock < half_clocks_per_sample; curclock++)
-		{
-if (LOG_TIMING | LOG_LOWPARAM | LOG_GLOTTAL | LOG_TRANSITION)
+void votrax_sc01_device::build_lowpass_filter(double *a, double *b,
+											  double c1t, // Unswitched cap, over amp-op, top
+											  double c1b) // Switched cap, over amp-op, bottom
 {
-	if (m_counter_34 % 32 == 0 && m_master_clock == 0)
-	{
-	if (LOG_TIMING)
-		osd_printf_debug("MCLK C034 L070 L072 BET1  P1   P2  PHI1 PHI2 PH1' PH2' SUBC C088 C084 L092 IIRQ ");
-	if (LOG_LOWPARAM)
-		osd_printf_debug("F132 F114 F112 F142 L080 ");
-	if (LOG_GLOTTAL)
-		osd_printf_debug("C220 C222 C224 C234 C236 FGAT GLSY ");
-	if (LOG_TRANSITION)
-		osd_printf_debug("0625 C046 L046 A0-2 L168 L170  FC   VA   FA   F1   F2   F3   F2Q ");
-	osd_printf_debug("\n");
-	}
-	if (LOG_TIMING)
-		osd_printf_debug("%4X %4X %4X %4X %4X %4X %4X %4X %4X %4X %4X %4X %4X %4X %4X %4X ", m_master_clock, m_counter_34, m_latch_70, m_latch_72, m_beta1, m_p1, m_p2, m_phi1, m_phi2, m_phi1_20, m_phi2_20, m_subphoneme_count, m_clock_88, m_counter_84, m_latch_92, m_internal_request);
-	if (LOG_LOWPARAM)
-		osd_printf_debug("%d %d %d %d %d ", m_srff_132, m_srff_114, m_srff_112, m_srff_142, m_latch_80);
-	if (LOG_GLOTTAL)
-		osd_printf_debug("%4X %4X %4X %4X %4X %4X %4X ", m_counter_220, m_counter_222, m_counter_224, m_counter_234, m_counter_236, m_fgate, m_glottal_sync);
-	if (LOG_TRANSITION)
-		osd_printf_debug("%4X %4X %4X %4X %4X %4X %4X %4X %4X %4X %4X %4X %4X ", m_0625_clock, m_counter_46, m_latch_46, m_latch_72 & 7, m_latch_168, m_latch_170, m_fc, m_va, m_fa, m_f1, m_f2, m_f3, m_f2q);
-	osd_printf_debug("\n");
-}
-
-			//==============================================
-			//
-			// Timing circuit (patent figure 2a)
-			//
-			//==============================================
-
-			// update master clock
-			m_master_clock ^= 1;
-
-			// on the falling edge of the master clock, advance the 10-bit counter at 34
-			uint8_t old_latch_72 = m_latch_72;
-			if (m_master_clock == 0)
-				m_counter_34 = (m_counter_34 + 1) & 0x3ff;
-			else
-			{
-				m_latch_70 = m_counter_34 & 0xf;
-				m_latch_72 = ((m_counter_34 >> 4) & 7) | ((m_counter_34 >> 6) & 8);
-			}
-
-			// derive beta 1 clock:
-			//  set if m_latch_70.0 == 1
-			//  reset if m_latch_70.0 == 0
-//          uint8_t old_beta1 = m_beta1;
-			m_beta1 = BIT(m_latch_70, 0);
-
-			// derive p2 clock:
-			//  set if (m_counter_34.P_CLOCK_BIT & clock) == 1
-			//  reset if (m_counter_34.P_CLOCK_BIT == 0)
-			uint8_t old_p2 = m_p2;
-			if (BIT(m_counter_34, P_CLOCK_BIT) & m_master_clock)
-				m_p2 = 1;
-			else if (!BIT(m_counter_34, P_CLOCK_BIT))
-				m_p2 = 0;
-
-			// derive p1 clock:
-			//  set if (!m_counter_34.P_CLOCK_BIT & clock) == 1
-			//  reset if (m_counter_34.P_CLOCK_BIT == 1)
-//          uint8_t old_p1 = m_p1;
-			if (BIT(~m_counter_34, P_CLOCK_BIT) & m_master_clock)
-				m_p1 = 1;
-			else if (BIT(m_counter_34, P_CLOCK_BIT))
-				m_p1 = 0;
-
-			// derive phi2 clock:
-			//  set if (m_counter_34.PHI_CLOCK_BIT & clock) == 1
-			//  reset if (m_counter_34.PHI_CLOCK_BIT == 0)
-			uint8_t old_phi2 = m_phi2;
-			if (BIT(m_counter_34, PHI_CLOCK_BIT) & m_master_clock)
-				m_phi2 = 1;
-			else if (!BIT(m_counter_34, PHI_CLOCK_BIT))
-				m_phi2 = 0;
-
-			// derive phi1 clock:
-			//  set if (!m_counter_34.PHI_CLOCK_BIT & clock) == 1
-			//  reset if (m_counter_34.PHI_CLOCK_BIT == 1)
-			uint8_t old_phi1 = m_phi1;
-			if (BIT(~m_counter_34, PHI_CLOCK_BIT) & m_master_clock)
-				m_phi1 = 1;
-			else if (BIT(m_counter_34, PHI_CLOCK_BIT))
-				m_phi1 = 0;
-
-			// derive alternate phi2 clock:
-			//  set if (m_counter_34.PHI_CLOCK_BIT & clock) == 1
-			//  reset if (m_counter_34.PHI_CLOCK_BIT == 0)
-			uint8_t old_phi2_20 = m_phi2_20;
-			if (BIT(m_counter_34, PHI_CLOCK_BIT + 2) & m_master_clock)
-				m_phi2_20 = 1;
-			else if (!BIT(m_counter_34, PHI_CLOCK_BIT + 2))
-				m_phi2_20 = 0;
-
-			// derive alternate phi1 clock:
-			//  set if (!m_counter_34.PHI_CLOCK_BIT & clock) == 1
-			//  reset if (m_counter_34.PHI_CLOCK_BIT == 1)
-//          uint8_t old_phi1_20 = m_phi1_20;
-			if (BIT(~m_counter_34, PHI_CLOCK_BIT + 2) & m_master_clock)
-				m_phi1_20 = 1;
-			else if (BIT(m_counter_34, PHI_CLOCK_BIT + 2))
-				m_phi1_20 = 0;
-
-			// determine rising edges of each clock of interest
-//          uint8_t beta1_rising = (old_beta1 ^ m_beta1) & m_beta1;
-			uint8_t p2_rising = (old_p2 ^ m_p2) & m_p2;
-//          uint8_t p1_rising = (old_p1 ^ m_p1) & m_p1;
-			uint8_t phi2_rising = (old_phi2 ^ m_phi2) & m_phi2;
-			uint8_t phi1_rising = (old_phi1 ^ m_phi1) & m_phi1;
-			uint8_t phi2_20_rising = (old_phi2_20 ^ m_phi2_20) & m_phi2_20;
-//          uint8_t phi1_20_rising = (old_phi1_20 ^ m_phi1_20) & m_phi1_20;
-			uint8_t a0_rising = BIT((old_latch_72 ^ m_latch_72) & m_latch_72, 0);
-			uint8_t a2_rising = BIT((old_latch_72 ^ m_latch_72) & m_latch_72, 2);
-			uint8_t _125k_rising = BIT((old_latch_72 ^ m_latch_72) & m_latch_72, 3);
-
-			// track subphoneme counter state
-			if (!(m_latch_42 | m_phi1))
-				m_subphoneme_count = 0;
-			else
-				m_subphoneme_count++;
-			if (p2_rising)
-				m_latch_42 = (m_subphoneme_count < m_subphoneme_period);
-
-			// update the state of the subphoneme clock line
-			uint8_t old_clock_88 = m_clock_88;
-			m_clock_88 = !m_latch_42;   //!(m_latch_42 | m_phi1); -- figure 7 seems to be wrong here
-			uint8_t clock_88_rising = (old_clock_88 ^ m_clock_88) & m_clock_88;
-
-			// the A/R line holds the counter in reset except during phoneme processing,
-			// when it is clocked on the rising edge of the subphoneme timer clock
-			if (m_internal_request != CLEAR_LINE)
-				m_counter_84 = 0xf;
-			else if (clock_88_rising)
-			{
-				m_counter_84 = (m_counter_84 - 1) & 0x0f;
-osd_printf_debug("counter=%d\n", m_counter_84);
-			}
-
-			// clock the zero count latch
-			if (p2_rising)
-				m_latch_92 = ((m_counter_84 == 0) | (m_latch_92 << 1)) & 3;
-
-			// once both bits are set, the request line goes high
-			if (m_latch_92 == 3)
-			{
-				// if the request line was previously low, reset the VD/CLD flip-flops
-				if (m_internal_request == CLEAR_LINE)
-				{
-					m_srff_112 = m_srff_114 = false;
-				}
-				m_internal_request = ASSERT_LINE;
-			}
-
-			//==============================================
-			//
-			// Low parameter clocking (patent figure 2b)
-			//
-			//==============================================
-
-			// fetch ROM data; note that the address lines come directly from
-			// counter_34 and not from the latches, which are 1 cycle delayed
-			uint8_t romdata = m_rom[(m_phoneme << 3) | ((m_counter_34 >> 4) & 7)];
-
-			// update the ROM data; ROM format is (upper nibble/lower nibble)
-			//  +00 = F1 parameter / 0
-			//  +01 = F2 parameter / 0
-			//  +02 = FC parameter / 0
-			//  +03 = F3 parameter / CL
-			//  +04 = F2Q Parameter / CLD
-			//  +05 = VA Parameter / VD
-			//  +06 = FA Parameter / PAC
-			//  +07 = Phoneme timing (full 7 bits)
-
-			// latch a new value from ROM on phi2
-			uint8_t a = m_latch_72 & 7;
-			uint8_t romdata_swapped;
-			if (phi2_rising)
-			{
-				switch (a)
-				{
-					// update CL
-					case 3:
-						m_srff_132 = m_srff_114 && BIT(~romdata, 3);
-						break;
-
-					// update CLD
-					case 4:
-						romdata_swapped = (BIT(romdata, 0) << 3) | (BIT(romdata, 1) << 2) | (BIT(romdata, 2) << 1) | (BIT(romdata, 3) << 0);
-						if (m_counter_84 != 0 && romdata_swapped == (m_counter_84 ^ 0xf))
-						{
-							m_srff_114 = true;
-						}
-						break;
-
-					// update VD
-					case 5:
-						romdata_swapped = (BIT(romdata, 0) << 3) | (BIT(romdata, 1) << 2) | (BIT(romdata, 2) << 1) | (BIT(romdata, 3) << 0);
-						if (m_counter_84 != 0 && romdata_swapped == (m_counter_84 ^ 0xf))
-						{
-							m_srff_112 = true;
-						}
-						break;
-
-					// update FF == PAC & (VA | FA)
-					case 6:
-						m_srff_142 = BIT(romdata, 3);
-						break;
-
-					// update PH
-					case 7:
-						if (m_latch_80 != (romdata & 0x7f))
-						{
-							m_latch_80 = romdata & 0x7f;
-osd_printf_debug("[PH=%02X]\n", m_latch_80);
-							uint32_t old_period = m_subphoneme_period;
-							update_subphoneme_clock_period();
-							m_subphoneme_count = (m_subphoneme_count * m_subphoneme_period) / old_period;
-							m_phoneme_timer->adjust(attotime::zero);
-						}
-						break;
-				}
-			}
-
-			//==============================================
-			//
-			// Glottal circuit (patent figure 6)
-			//
-			//==============================================
-
-			// determine the TC output from the counters (note that TC requires ET)
-			uint8_t counter_222_tc = (m_counter_222 == 0xf);
-			uint8_t counter_220_tc = (m_counter_220 == 0xf && counter_222_tc);
-			uint8_t counter_224_tc = (m_counter_224 == 0xf && counter_222_tc);
-
-			// clock glottal counter 224 on rising edge of a0
-			if (a0_rising)
-			{
-				// counter 224 is only enabled if TC of counter 222 is 1
-				if (counter_222_tc)
-				{
-					// if counter 220's TC is 1, do a load instead of a count
-					if (counter_220_tc)
-						m_counter_224 = (m_inflection << 1) | ((~m_f1 & 0x8) >> 3);
-					else
-						m_counter_224 = (m_counter_224 + 1) & 0xf;
-				}
-			}
-
-			// clock remaining glottal counters (220, 222, 236) on rising edge of phi2
-			if (phi2_20_rising)
-			{
-				// counter 220 is only enabled if TC of counter 222 is 1
-				if (counter_222_tc)
-				{
-					// if counter 220's TC is 1, do a load instead of a count
-					if (counter_220_tc)
-						m_counter_220 = (m_inflection << 1) | ((~m_f1 & 0x8) >> 3);
-					else
-						m_counter_220 = (m_counter_220 + 1) & 0xf;
-				}
-
-				// counter 222 is always enabled
-				if (1)
-				{
-					// if counter 220's TC is 1, do a load instead of a count
-					if (counter_220_tc)
-						m_counter_222 = (~m_f1 & 0x7) << 1;
-					else
-						m_counter_222 = (m_counter_222 + 1) & 0xf;
-				}
-
-				// counter 236 is always enabled
-				if (1)
-				{
-					m_counter_236 = (m_counter_236 + 1) & 0xf;
-
-					// rising edge of Q1 from counter 236 clocks counter 234
-					if ((m_counter_236 & 0x3) == 0x2)
-					{
-						// counter 234 is only enabled if it has not reached terminal
-						if (m_counter_234 != 0xf)
-							m_counter_234 = (m_counter_234 + 1) & 0xf;
-					}
-				}
-			}
-
-			// update FGATE state
-			if (counter_220_tc)
-				m_fgate = 0;
-			if (counter_224_tc)
-				m_fgate = 1;
-
-			// apply asynchronous clear to counters 234/236
-			if (counter_220_tc && m_phi1_20)
-				m_counter_236 = m_counter_234 = 0;
-
-			// derive glottal circuit output signals
-#if !TEMP_HACKS
-			uint8_t old_glottal_sync = m_glottal_sync;
-#endif
-			m_glottal_sync = (m_counter_234 == 0);
-			glottal_out = s_glottal_wave[m_counter_234];
-
-			//==============================================
-			//
-			// Transition circuit (patent figure 3a/3b)
-			//
-			//==============================================
-
-			// divide 1.25k clock by 2 (lower-left of 46)
-			uint8_t old_0625_clock = m_0625_clock;
-			if (_125k_rising)
-				m_0625_clock = !m_0625_clock;
-			uint8_t _0625_rising = (old_0625_clock ^ m_0625_clock) & m_0625_clock;
-
-			// update counter above
-			if (_0625_rising)
-			{
-				if (m_counter_46 == 0xf)
-					m_counter_46 = 0xd;
-				else
-					m_counter_46 = (m_counter_46 + 1) & 0xf;
-			}
-
-			// and then the latch to the right
-			if (a2_rising)
-				m_latch_46 = (BIT(m_counter_46, 1) << 0) |
-								(BIT(m_latch_46, 0) << 1) |
-								(m_0625_clock << 2) |
-								(BIT(m_latch_46, 2) << 3);
-
-#if TEMP_HACKS
-			m_latch_46 = 0xf;
-#endif
-
-			// determine the read/write signal
-			uint8_t ram_write = 0;
-			switch (a)
-			{
-				// write if not FF and low 2 bits of latch
-				// FF is the S/R flip-flop at 142 ANDed with !(/FA & /VA)
-				case 0: case 1: case 2: case 3: case 4:
-					if ((m_srff_142 && !((m_fa == 0) && (m_va == 0))) == 0 && (m_latch_46 & 0x3) == 0x3)
-						ram_write = 1;
-					break;
-
-				case 5:
-					if ((m_latch_46 & 0xc) == 0xc && m_srff_112)
-					{
-						ram_write = 1;
-					}
-					break;
-
-				case 6:
-					if ((m_latch_46 & 0xc) == 0xc && m_srff_114)
-					{
-						ram_write = 1;
-					}
-					break;
-			}
-
-			// gate on the phi2 clock (OR gate @ 172)
-			ram_write &= m_phi2;
-
-			// write the transitioned values to RAM if requested
-			// (note we consolidate the serial addition and clocking steps here)
-			if (ram_write)
-			{
-				uint8_t old = (m_latch_168 << 4) | m_latch_170;
-				m_ram[a] = old - (old >> 3) + ((romdata & 0xf0) >> 3);
-			}
-
-			// latch some parameter values on rising edge of phi2
-			if (phi2_rising)
-			{
-				switch (a)
-				{
-					case 2:
-						m_fc = m_latch_168;
-						break;
-
-					case 5:
-						m_va = m_latch_168;
-						break;
-
-					case 6:
-						m_fa = m_latch_168;
-						break;
-				}
-			}
-
-			// latch remaining parameter values on rising edge of (phi2 & glottal sync)
-#if TEMP_HACKS
-			if (phi2_rising)
-#else
-			uint8_t old_phi2_glottal = (old_phi2 & old_glottal_sync);
-			uint8_t new_phi2_glottal = m_phi2 & m_glottal_sync;
-			if ((old_phi2_glottal ^ new_phi2_glottal) & new_phi2_glottal)
-#endif
-				switch (a)
-				{
-					case 0:
-						m_f1 = m_latch_168;
-						break;
-
-					case 1:
-						m_f2 = (m_latch_168 << 1) | (m_latch_170 >> 3);
-						break;
-
-					case 3:
-						m_f3 = m_latch_168;
-						break;
-
-					case 4:
-						m_f2q = m_latch_168;
-						break;
-				}
-
-			// latch value from RAM on rising edge of phi1
-			if (phi1_rising)
-			{
-				m_latch_168 = m_ram[a] >> 4;
-				m_latch_170 = m_ram[a] & 0xf;
-			}
-
-			//==============================================
-			//
-			// Noise generator circuit (patent figure 8)
-			//
-			//==============================================
-
-			// nose is clocked by the NOR of /FA and P1
-			uint8_t old_noise_clock = m_noise_clock;
-			m_noise_clock = !((m_fa == 0) | m_p1);
-			uint8_t noise_clock_rising = (old_noise_clock ^ m_noise_clock) & m_noise_clock;
-			uint8_t noise_clock_falling = (old_noise_clock ^ m_noise_clock) & old_noise_clock;
-
-			// falling edge clocks the shift register
-			if (noise_clock_falling)
-			{
-				// shift register 252 is actually 4 shift registers (2 4-bit, 2 5-bit)
-				// d1 and d3 are the 4-bit registers, d2 and d4 are the 5-bit registers
-				// XOR'ed input goes into d4, which shifts in to d2, then d3, then d1
-				// thus the full 18-bit value is effectively
-				//
-				//  d4 = (m_shift_252 >> 0) & 0x1f;
-				//  d2 = (m_shift_252 >> 5) & 0x1f;
-				//  d3 = (m_shift_252 >> 10) & 0xf;
-				//  d1 = (m_shift_252 >> 14) & 0xf;
-				//
-				// input at the low end is ((d1+4 ^ d2+5) ^ (d4+4 ^ d4+5)) ^ !(counter2 | counter3)
-				// output is tapped at d3+4
-
-				uint32_t old_shift = m_shift_252;
-				m_shift_252 <<= 1;
-				m_shift_252 |= ((BIT(old_shift, 17) ^ BIT(old_shift, 9)) ^ (BIT(old_shift, 3) ^ BIT(old_shift, 4))) ^
-									((m_counter_250 & 0xc) == 0);
-			}
-
-			// rising edge clocks the counter
-			if (noise_clock_rising)
-			{
-				// counter is reset to 1 if terminal, otherwise it increments
-				if (m_counter_250 == 0xf)
-					m_counter_250 = 0x1;
-				else
-					m_counter_250 = (m_counter_250 + 1) & 0xf;
-			}
-
-			// compute final noise out signal
-			noise_out_digital = !(BIT(m_shift_252, 13) & (m_fgate | (m_va == 0)));
-		}
-
-		// TODO: cache the filters
-		// filter coefs
-		double k[3], a[4], b[4];
-
-		// base frequencies
-		double fc = m_master_clock_freq / 30.0; // Nominal is 20KHz
-		double fs = stream.sample_rate();
-
-		// useful temporaries
-		double rcp, rcq, rca;
-
-		// amplification stage
-		static const double va_caps[4] = { 27, 53, 107, 213 };
-		double va_out = glottal_out * bits_to_caps(m_va, 4, va_caps) / 400;
-
-		shift_hist(va_out, m_va_hist, 4);
-
-
-		// noise shaping
-		static const double fa_caps[4] = { 27, 53, 107, 213 };
-		rcp = bits_to_caps(m_fa,  4, fa_caps);
-
-		shift_hist(-noise_out_digital * 400*rcp/(358.0*100000*566*(fc*rcp*1e-12 + 1.0/100000 + 1.0/2000)), m_ni_hist, 4);
-
-		k[0] = 400/(fc*358);
-		k[1] = 400*400/(fc*358*566);
-		k[2] = 400*400/(fc*fc*358*358);
-
-		filter_s_to_z(k, fs, a, b);
-		double no_out = apply_filter(m_ni_hist, m_no_hist, a, b);
-		shift_hist(no_out, m_no_hist, 4);
-
-
-		// stage 1 filter
-
-		static const double s1_p_caps[4] = { 16.4, 33, 66, 130 };
-		rcp = 24 + bits_to_caps(m_f1, 4, s1_p_caps);
-		rcq = 20;
-
-		k[0] = 253/(fc*270);
-		k[1] = 1080*rcq/(fc*270*rcp);
-		k[2] = 1080*1080/(fc*fc*270*rcp);
-
-		filter_s_to_z(k, fs, a, b);
-		double s1_out = apply_filter(m_va_hist, m_s1_hist, a, b);
-		shift_hist(s1_out, m_s1_hist, 4);
-
-
-		// stage 2 filter, glottal half
-
-		static const double s2_p_caps[5] = { 14, 28, 56, 113, 226 };
-		static const double s2_q_caps[4] = { 23, 46, 93, 186 };
-		rcp = 46 + bits_to_caps(m_f2,  5, s2_p_caps);
-		rcq = 20 + bits_to_caps(m_f2q, 4, s2_q_caps);;
-
-		k[0] = 400/(fc*470);
-		k[1] = 620*rcq/(fc*470*rcp);
-		k[2] = 620*620/(fc*fc*470*rcp);
-
-		filter_s_to_z(k, fs, a, b);
-		double s2g_out = apply_filter(m_s1_hist, m_s2g_hist, a, b);
-		shift_hist(s2g_out, m_s2g_hist, 4);
-
-
-		// stage 2 filter, noise half (rcp and rcq kept from stage 2 glottal)
-
-		static const double s2_n_caps[5] = { 19, 38, 76, 152 };
-		rca = bits_to_caps(m_fc, 4, s2_n_caps);
-
-		shift_hist(-no_out*rcq*rca/(470*rcp), m_s2ni_hist, 4);
-
-		k[0] = 400/(fc*470);
-		k[1] = 620*rcq/(fc*470*rcp);
-		k[2] = 620*620/(fc*fc*470*rcp);
-
-		filter_s_to_z(k, fs, a, b);
-		double s2n_out = apply_filter(m_s2ni_hist, m_s2n_hist, a, b);
-		shift_hist(s2n_out, m_s2n_hist, 4);
-
-		// sum the stage 2 outputs
-		double s2_out = s2g_out + s2n_out;
-		shift_hist(s2_out, m_s2_hist, 4);
-
-
-		// stage 3 filter
-
-		static const double s3_p_caps[4] = { 21, 42, 84, 168 };
-		rcp = 76 + bits_to_caps(m_f3, 4, s3_p_caps);
-		rcq = 20;
-
-		k[0] = 0;
-		k[1] = 420*rcq/(fc*390*rcp);
-		k[2] = 420*420/(fc*fc*390*rcp);
-
-		filter_s_to_z(k, fs, a, b);
-		double s3_out = apply_filter(m_s2_hist, m_s3_hist, a, b);
-		shift_hist(s3_out, m_s3_hist, 4);
-
-
-		// stage 4 filter, noise injection
-
-		// The resulting non-amplifying filter is identical, so we
-		// inject instead of splitting
-
-		static const double s4_n_caps[4] = { 24, 48, 96, 192 };
-		rca = 115 + bits_to_caps(~m_fc, 4, s4_n_caps);
-
-		shift_hist(s3_out + no_out*470/rca, m_s4i_hist, 4);
-
-
-		// stage 4 filter
-
-		rcp = 30;
-		rcq = 20;
-
-		k[0] = 0;
-		k[1] = 338*rcq/(fc*470*rcp);
-		k[2] = 338*338/(fc*fc*470*rcp);
-
-		filter_s_to_z(k, fs, a, b);
-		double s4_out = apply_filter(m_s4i_hist, m_s4_hist, a, b);
-		shift_hist(s4_out, m_s4_hist, 4);
-
-
-		// TODO: apply closure circuit (undocumented)
-
-		// output the current result
-		*dest++ = int16_t(s4_out * 4000);
-	}
-}
+	// Compute the only coefficient we care about
+	double k = c1b / (m_cclock * c1t);
 
+	// Compute the filter cutoff frequency
+	double fpeak = 1/(2*M_PI*k);
 
+	// Turn that into a warp multiplier
+	double zc = 2*M_PI*fpeak/tan(M_PI*fpeak / m_sclock);
 
-//**************************************************************************
-//  DEVICE INTERFACE
-//**************************************************************************
-
-//-------------------------------------------------
-//  rom_region - return a pointer to the device's
-//  internal ROM region
-//-------------------------------------------------
+	// Finally compute the result of the z-transform
+	double m = zc*k;
 
-const tiny_rom_entry *votrax_sc01_device::device_rom_region() const
-{
-	return ROM_NAME( votrax_sc01 );
+	a[0] = 1;
+	b[0] = 1+m;
+	b[1] = 1-m;
 }
 
+/*
+  Used to shape the white noise
+
+         +-------------------------------------------------------------------+
+         |                                                                   |
+         +--|C1|--+---------|C3|----------+--|C4|--+                         |
+         |        |      +        +       |        |                         |
+   Vi    |  |\    |     (1)      (1)      |        |       +        +        |
+   -|R0|-+--+-\   |      |        |       |  |\    |      (1)      (1)       |
+            |  >--+--(2)-+--|C2|--+---(2)-+--+-\   |       |        |        |
+          0-++/          |                   |  >--+--(2)--+--|C5|--+---(2)--+
+            |/          Vo                 0-++/
+                                             |/
+   Equivalent:
+
+         +------------------|R5|-------------------+
+         |                                         |
+         +--|C1|--+---------|C3|----------+--|C4|--+
+         |        |                       |        |
+   Vi    |  |\    |                       |        |
+   -|R0|-+--+-\   |                       |  |\    |
+            |  >--+---------|R2|----------+--+-\   |
+          0-++/   |                          |  >--+
+            |/   Vo                        0-++/
+                                             |/
+
+  We assume r0 = r2
+*/
 
-//-------------------------------------------------
-//  device_start - handle device startup
-//-------------------------------------------------
-
-void votrax_sc01_device::device_start()
+void votrax_sc01_device::build_noise_shaper_filter(double *a, double *b,
+												   double c1,  // Cap over first amp-op
+												   double c2t, // Unswitched cap between amp-ops, input, top
+												   double c2b, // Switched cap between amp-ops, input, bottom
+												   double c3,  // Cap over second amp-op
+												   double c4)  // Switched cap after second amp-op
 {
-	// initialize internal state
-	m_master_clock_freq = clock();
-	m_stream = stream_alloc(0, 1, m_master_clock_freq / 16);
-	m_phoneme_timer = timer_alloc();
-	m_rom = memregion("phoneme")->base();
+	// Coefficients of H(s) = k1*s / (1 + k2*s + k3*s^2)
+	double k0 = c2t*c3*c2b/c4;
+	double k1 = c2t*(m_cclock * c2b);
+	double k2 = c1*c2t*c3/(m_cclock * c4);
 
-	// reset inputs
-	m_inflection = 0;
-	m_phoneme = 0x3f;
-
-	// reset outputs
-	m_request_cb.resolve_safe();
-	m_request_state = ASSERT_LINE;
-	m_internal_request = ASSERT_LINE;
-
-	// save inputs
-	save_item(NAME(m_inflection));
-	save_item(NAME(m_phoneme));
+	// Estimate the filter cutoff frequency
+	double fpeak = sqrt(1/k2)/(2*M_PI);
 
-	// save outputs
-	save_item(NAME(m_request_state));
-	save_item(NAME(m_internal_request));
-
-	// save timing circuit
-	save_item(NAME(m_master_clock_freq));
-	save_item(NAME(m_master_clock));
-	save_item(NAME(m_counter_34));
-	save_item(NAME(m_latch_70));
-	save_item(NAME(m_latch_72));
-	save_item(NAME(m_beta1));
-	save_item(NAME(m_p2));
-	save_item(NAME(m_p1));
-	save_item(NAME(m_phi2));
-	save_item(NAME(m_phi1));
-	save_item(NAME(m_subphoneme_period));
-	save_item(NAME(m_subphoneme_count));
-	save_item(NAME(m_clock_88));
-	save_item(NAME(m_latch_42));
-	save_item(NAME(m_counter_84));
-	save_item(NAME(m_latch_92));
-
-	// save low parameter clocking
-	save_item(NAME(m_srff_132));
-	save_item(NAME(m_srff_114));
-	save_item(NAME(m_srff_112));
-	save_item(NAME(m_srff_142));
-	save_item(NAME(m_latch_80));
-
-	// save glottal circuit
-	save_item(NAME(m_counter_220));
-	save_item(NAME(m_counter_222));
-	save_item(NAME(m_counter_224));
-	save_item(NAME(m_counter_234));
-	save_item(NAME(m_counter_236));
-	save_item(NAME(m_fgate));
-	save_item(NAME(m_glottal_sync));
-
-	// save transition circuit
-	save_item(NAME(m_0625_clock));
-	save_item(NAME(m_counter_46));
-	save_item(NAME(m_latch_46));
-	save_item(NAME(m_ram));
-	save_item(NAME(m_latch_168));
-	save_item(NAME(m_latch_170));
-	save_item(NAME(m_f1));
-	save_item(NAME(m_f2));
-	save_item(NAME(m_fc));
-	save_item(NAME(m_f3));
-	save_item(NAME(m_f2q));
-	save_item(NAME(m_va));
-	save_item(NAME(m_fa));
-
-	// save noise generator circuit
-	save_item(NAME(m_noise_clock));
-	save_item(NAME(m_shift_252));
-	save_item(NAME(m_counter_250));
-
-	// save filter histories
-	save_item(NAME(m_ni_hist));
-	save_item(NAME(m_no_hist));
-	save_item(NAME(m_va_hist));
-	save_item(NAME(m_s1_hist));
-	save_item(NAME(m_s2g_hist));
-	save_item(NAME(m_s2n_hist));
-	save_item(NAME(m_s2ni_hist));
-	save_item(NAME(m_s2_hist));
-	save_item(NAME(m_s3_hist));
-	save_item(NAME(m_s4i_hist));
-	save_item(NAME(m_s4_hist));
-}
+	// Turn that into a warp multiplier
+	double zc = 2*M_PI*fpeak/tan(M_PI*fpeak / m_sclock);
 
+	// Finally compute the result of the z-transform
+	double m0 = zc*k0;
+	double m1 = zc*k1;
+	double m2 = zc*zc*k2;
 
-//-------------------------------------------------
-//  device_reset - handle device reset
-//-------------------------------------------------
-
-void votrax_sc01_device::device_reset()
-{
-	// set the initial state
-	m_stream->update();
-
-	// reset inputs
-	m_phoneme = 0x3f;
-	m_request_cb(m_internal_request = m_request_state = ASSERT_LINE);
-
-	// reset timing circuit
-	m_master_clock = 0;
-	m_counter_34 = 0;
-	m_latch_70 = 0;
-	m_latch_72 = 0;
-	m_beta1 = 0;
-	m_p2 = 0;
-	m_p1 = 0;
-	m_phi2 = 0;
-	m_phi1 = 0;
-	m_subphoneme_period = 1000;
-	m_subphoneme_count = 0;
-	m_clock_88 = 0;
-	m_latch_42 = 0;
-	m_counter_84 = 0;
-	m_latch_92 = 0;
-
-	// reset low parameter clocking
-	m_srff_132 = false;
-	m_srff_114 = false;
-	m_srff_112 = false;
-	m_srff_142 = false;
-	m_latch_80 = 50;
-	update_subphoneme_clock_period();
-
-	// reset glottal circuit
-	m_counter_220 = 0;
-	m_counter_222 = 0;
-	m_counter_224 = 0;
-	m_counter_234 = 0;
-	m_counter_236 = 0;
-	m_fgate = 0;
-	m_glottal_sync = 0;
-
-	// reset transition circuit
-	m_0625_clock = 0;
-	m_counter_46 = 0;
-	m_latch_46 = 0;
-	memset(m_ram, 0, sizeof(m_ram));
-	m_latch_168 = 0;
-	m_latch_170 = 0;
-	m_f1 = 0;
-	m_f2 = 0;
-	m_fc = 0;
-	m_f3 = 0;
-	m_f2q = 0;
-	m_va = 0;
-	m_fa = 0;
-
-	// reset noise circuit
-	m_noise_clock = 0;
-	m_shift_252 = 0;
-	m_counter_250 = 0;
-
-	// reset filter histories
-	memset(m_ni_hist,   0, sizeof(m_ni_hist));
-	memset(m_no_hist,   0, sizeof(m_no_hist));
-	memset(m_va_hist,   0, sizeof(m_va_hist));
-	memset(m_s1_hist,   0, sizeof(m_s1_hist));
-	memset(m_s2g_hist,  0, sizeof(m_s2g_hist));
-	memset(m_s2n_hist,  0, sizeof(m_s2n_hist));
-	memset(m_s2ni_hist, 0, sizeof(m_s2ni_hist));
-	memset(m_s2_hist,   0, sizeof(m_s2_hist));
-	memset(m_s3_hist,   0, sizeof(m_s3_hist));
-	memset(m_s4i_hist,  0, sizeof(m_s4i_hist));
-	memset(m_s4_hist,   0, sizeof(m_s4_hist));
+	a[0] = m0;
+	a[1] = 0;
+	a[2] = -m0;
+	b[0] = 1+m1+m2;
+	b[1] = 2-2*m2;
+	b[2] = 1-m1+m2;
 }
 
+/*
+  Noise injection in f2
 
-//-------------------------------------------------
-//  device_clock_changed - handle dynamic clock
-//  changes by altering our output frequency
-//-------------------------------------------------
-
-void votrax_sc01_device::device_clock_changed()
-{
-	// compute new frequency of the master clock, and update if changed
-	uint32_t newfreq = clock();
-	if (newfreq != m_master_clock_freq)
-	{
-		// if we have a stream
-		if (m_stream != nullptr)
-		{
-			m_stream->update();
-			m_stream->set_sample_rate(newfreq / 16);
-		}
-
-		// determine how many clock ticks remained on the phoneme timer
-		uint64_t remaining = m_phoneme_timer->remaining().as_ticks(m_master_clock_freq);
-
-		// recompute the master clock
-		m_master_clock_freq = newfreq;
-
-		// adjust the phoneme timer to the same number of ticks based on the new frequency
-		if (remaining > 0)
-			m_phoneme_timer->adjust(attotime::from_ticks(remaining, newfreq));
-	}
-}
-
+  |                     +--[R2]--+        +--[R1]-------- Vi
+  |                     |        |        |
+  |                     +--|C2|--+<V1     +--|C3|--+
+  |                     |        |        |        |
+  |                     |  |\    |        |  |\    |
+  |                +----+--+-\   |        +--+-\   |
+  |                |       |  >--+--[Rx]--+  |  >--+----- Vo
+  |                |     0-++/             0-++/   |
+  |                |       |/    +--[R0]--+  |/    |
+  |                |             |        |        |
+  |                |             |    /|  |        |
+  |                |             |   /-+--+--[R0]--+
+  |                +--[R4]-------+--<  |
+  |                            V2^   \++-0
+  |                                   \|
 
-//-------------------------------------------------
-//  device_timer - handle device timer
-//-------------------------------------------------
+  We drop r0/r1 out of the equation (it factorizes), and we rescale so
+  that H(infinity)=1.
+*/
 
-void votrax_sc01_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+void votrax_sc01_device::build_injection_filter(double *a, double *b,
+												double c1b, // Switched cap, input, bottom
+												double c2t, // Unswitched cap, over first amp-op, top
+												double c2b, // Switched cap, over first amp-op, bottom
+												double c3,  // Cap between the two op-amps
+												double c4)  // Cap over second op-amp
 {
-	// force a stream update
-	m_stream->update();
-
-	// if we're requesting more data, no need for timing
-	if (m_request_state == ASSERT_LINE)
-		return;
-
-	// if we're supposed to have fired, do it now
-	if (m_internal_request == ASSERT_LINE)
-	{
-osd_printf_debug("%s: REQUEST\n", timer.machine().time().as_string(3));
-		m_request_cb(m_request_state = ASSERT_LINE);
-		return;
-	}
-
-	// account for the rest of this subphoneme clock
-	uint32_t clocks_until_request = 0;
-	if (m_counter_84 != 0)
-	{
-		if (m_subphoneme_count < m_subphoneme_period)
-			clocks_until_request += m_subphoneme_period - m_subphoneme_count;
-		clocks_until_request += m_subphoneme_period * (m_counter_84 - 1);
-	}
-
-	// plus 1/2
-	clocks_until_request = std::max(clocks_until_request, uint32_t(1 << P_CLOCK_BIT) / 2);
-	timer.adjust(attotime::from_ticks(clocks_until_request, m_master_clock_freq));
+	// First compute the three coefficients of H(s) = (k0 + k2*s)/(k1 - k2*s)
+	double k0 = m_cclock * c2t;
+	double k1 = m_cclock * (c1b * c3 / c2t - c2t);
+	double k2 = c2b;
+
+	// Don't pre-warp
+	double zc = 2*m_sclock;
+
+	// Finally compute the result of the z-transform
+	double m = zc*k2;
+
+	a[0] = k0 + m;
+	a[1] = k0 - m;
+	b[0] = k1 - m;
+	b[1] = k1 + m;
+
+	// That ends up in a numerically unstable filter.  Neutralize it for now.
+	a[0] = 1;
+	a[1] = 0;
+	b[0] = 1;
+	b[1] = 0;
 }
diff --git a/src/devices/sound/votrax.h b/src/devices/sound/votrax.h
index adf6b42..dd39efc 100644
--- a/src/devices/sound/votrax.h
+++ b/src/devices/sound/votrax.h
@@ -1,34 +1,20 @@
 // license:BSD-3-Clause
-// copyright-holders:Aaron Giles
+// copyright-holders:Olivier Galibert
 /***************************************************************************
 
     votrax.h
 
-    Simple VOTRAX SC-01 simulator based on sample fragments.
+    Votrax SC01A simulation
 
 ***************************************************************************/
 
 #pragma once
 
-#ifndef __VOTRAX_H__
-#define __VOTRAX_H__
-
-#include "sound/samples.h"
-
-
-//**************************************************************************
-//  INTERFACE CONFIGURATION MACROS
-//**************************************************************************
+#ifndef VOTRAX_H
+#define VOTRAX_H
 
 #define MCFG_VOTRAX_SC01_REQUEST_CB(_devcb) \
-	devcb = &votrax_sc01_device::set_request_callback(*device, DEVCB_##_devcb);
-
-
-//**************************************************************************
-//  TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> votrax_sc01_device
+	devcb = &downcast<votrax_sc01_device *>(device)->set_ar_callback(DEVCB_##_devcb);
 
 class votrax_sc01_device :  public device_t,
 							public device_sound_interface
@@ -37,12 +23,11 @@ public:
 	// construction/destruction
 	votrax_sc01_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
 
-	template<class _Object> static devcb_base &set_request_callback(device_t &device, _Object object) { return downcast<votrax_sc01_device &>(device).m_request_cb.set_callback(object); }
+	template<class _Object> devcb_base &set_ar_callback(_Object object) { return m_ar_cb.set_callback(object); }
 
-	// writers
-	DECLARE_WRITE8_MEMBER( write );
-	DECLARE_WRITE8_MEMBER( inflection_w );
-	DECLARE_READ_LINE_MEMBER( request ) { m_stream->update(); return m_request_state; }
+	DECLARE_WRITE8_MEMBER(write);
+	DECLARE_WRITE8_MEMBER(inflection_w);
+	DECLARE_READ_LINE_MEMBER(request) { m_stream->update(); return m_ar_state; }
 
 protected:
 	// device-level overrides
@@ -56,99 +41,144 @@ protected:
 	virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
 
 private:
-	// internal helpers
-	void update_subphoneme_clock_period();
-	static double bits_to_caps(uint32_t value, int caps_count, const double *caps_values);
-	static void shift_hist(double val, double *hist_array, int hist_size);
-	static void filter_s_to_z(const double *k, double fs, double *a, double *b);
-	static double apply_filter(const double *x, const double *y, const double *a, const double *b);
-
-	// internal state
-	sound_stream *              m_stream;               // output stream
-	emu_timer *                 m_phoneme_timer;        // phoneme timer
-	const uint8_t *               m_rom;                  // pointer to our ROM
-
-	// inputs
-	uint8_t                       m_inflection;           // 2-bit inflection value
-	uint8_t                       m_phoneme;              // 6-bit phoneme value
-
-	// outputs
-	devcb_write_line           m_request_cb;           // callback for request
-	uint8_t                       m_request_state;        // request as seen to the outside world
-	uint8_t                       m_internal_request;     // request managed by stream timing
-
-	// timing circuit
-	uint32_t                      m_master_clock_freq;    // frequency of the master clock
-	uint8_t                       m_master_clock;         // master clock
-	uint16_t                      m_counter_34;           // ripple counter @ 34
-	uint8_t                       m_latch_70;             // 4-bit latch @ 70
-	uint8_t                       m_latch_72;             // 4-bit latch @ 72
-	uint8_t                       m_beta1;                // beta1 clock state
-	uint8_t                       m_p2;                   // P2 clock state
-	uint8_t                       m_p1;                   // P1 clock state
-	uint8_t                       m_phi2;                 // phi2 clock state
-	uint8_t                       m_phi1;                 // phi1 clock state
-	uint8_t                       m_phi2_20;              // alternate phi2 clock state (20kHz)
-	uint8_t                       m_phi1_20;              // alternate phi1 clock state (20kHz)
-	uint32_t                      m_subphoneme_period;    // period of the subphoneme timer
-	uint32_t                      m_subphoneme_count;     // number of ticks executed already
-	uint8_t                       m_clock_88;             // subphoneme clock output @ 88
-	uint8_t                       m_latch_42;             // D flip-flop @ 42
-	uint8_t                       m_counter_84;           // 4-bit phoneme counter @ 84
-	uint8_t                       m_latch_92;             // 2-bit latch @ 92
-
-	// low parameter clocking
-	bool                        m_srff_132;             // S/R flip-flop @ 132
-	bool                        m_srff_114;             // S/R flip-flop @ 114
-	bool                        m_srff_112;             // S/R flip-flop @ 112
-	bool                        m_srff_142;             // S/R flip-flop @ 142
-	uint8_t                       m_latch_80;             // phoneme timing latch @ 80
-
-	// glottal circuit
-	uint8_t                       m_counter_220;          // 4-bit counter @ 220
-	uint8_t                       m_counter_222;          // 4-bit counter @ 222
-	uint8_t                       m_counter_224;          // 4-bit counter @ 224
-	uint8_t                       m_counter_234;          // 4-bit counter @ 234
-	uint8_t                       m_counter_236;          // 4-bit counter @ 236
-	uint8_t                       m_fgate;                // FGATE signal
-	uint8_t                       m_glottal_sync;         // Glottal Sync signal
-
-	// transition circuit
-	uint8_t                       m_0625_clock;           // state of 0.625kHz clock
-	uint8_t                       m_counter_46;           // 4-bit counter in block @ 46
-	uint8_t                       m_latch_46;             // 4-bit latch in block @ 46
-	uint8_t                       m_ram[8];               // RAM to hold parameters
-	uint8_t                       m_latch_168;            // 4-bit latch @ 168
-	uint8_t                       m_latch_170;            // 4-bit latch @ 170
-	uint8_t                       m_f1;                   // latched 4-bit F1 value
-	uint8_t                       m_f2;                   // latched 5-bit F2 value
-	uint8_t                       m_fc;                   // latched 4-bit FC value
-	uint8_t                       m_f3;                   // latched 4-bit F3 value
-	uint8_t                       m_f2q;                  // latched 4-bit F2Q value
-	uint8_t                       m_va;                   // latched 4-bit VA value
-	uint8_t                       m_fa;                   // latched 4-bit FA value
-
-	// noise generator circuit
-	uint8_t                       m_noise_clock;          // clock input to noise generator
-	uint32_t                      m_shift_252;            // shift register @ 252
-	uint8_t                       m_counter_250;          // 4-bit counter @ 250
-
-	// stages outputs history
-	double                      m_ni_hist[4];
-	double                      m_no_hist[4];
-	double                      m_va_hist[4];
-	double                      m_s1_hist[4];
-	double                      m_s2g_hist[4];
-	double                      m_s2ni_hist[4];
-	double                      m_s2n_hist[4];
-	double                      m_s2_hist[4];
-	double                      m_s3_hist[4];
-	double                      m_s4i_hist[4];
-	double                      m_s4_hist[4];
-
-	// static tables
-	static const char *const s_phoneme_table[64];
-	static const double s_glottal_wave[16];
+	// Possible timer parameters
+	enum {
+		T_COMMIT_PHONE,
+		T_END_OF_PHONE
+	};
+
+	static const char *const s_phone_table[64];
+	static const double s_glottal_wave[9];
+
+	sound_stream *m_stream;                         // Output stream
+	emu_timer *m_timer;                             // General timer
+	required_memory_region m_rom;                   // Internal ROM
+	u32 m_mainclock;                                // Current main clock
+	double m_sclock;                                // Stream sample clock (40KHz, main/18)
+	double m_cclock;                                // 20KHz capacitor switching clock (main/36)
+	u32 m_sample_count;                             // Sample counter, to cadence chip updates
+
+	// Inputs
+	u8 m_inflection;                                // 2-bit inflection value
+	u8 m_phone;                                     // 6-bit phone value
+
+	// Outputs
+	devcb_write_line m_ar_cb;                       // Callback for ar
+	bool m_ar_state;                                // Current ar state
+
+	// "Unpacked" current rom values
+	u8 m_rom_duration;                              // Duration in 5KHz units (main/144) of one tick, 16 ticks per phone, 7 bits
+	u8 m_rom_vd, m_rom_cld;                         // Duration in ticks of the "voice" and "closure" delays, 4 bits
+	u8 m_rom_fa, m_rom_fc, m_rom_va;                // Analog parameters, noise volume, noise freq cutoff and voice volume, 4 bits each
+	u8 m_rom_f1, m_rom_f2, m_rom_f2q, m_rom_f3;     // Analog parameters, formant frequencies and Q, 4 bits each
+	bool m_rom_closure;                             // Closure bit, true = silence at cld
+	bool m_rom_pause;                               // Pause bit
+
+	// Current interpolated values (8 bits each)
+	u8 m_cur_fa, m_cur_fc, m_cur_va;
+	u8 m_cur_f1, m_cur_f2, m_cur_f2q, m_cur_f3;
+
+	// Current committed values
+	u8 m_filt_fa, m_filt_fc, m_filt_va;             // Analog parameters, noise volume, noise freq cutoff and voice volume, 4 bits each
+	u8 m_filt_f1, m_filt_f2, m_filt_f2q, m_filt_f3; // Analog parameters, formant frequencies/Q on 4 bits except f2 on 5 bits
+
+	// Internal counters
+	u16 m_phonetick;                                // 9-bits phone tick duration counter
+	u8  m_ticks;                                    // 5-bits tick counter
+	u8  m_pitch;                                    // 7-bits pitch counter
+	u8  m_closure;                                  // 5-bits glottal closure counter
+	u8  m_update_counter;                           // 6-bits counter for the 625Hz (main/1152) and 208Hz (main/3456) update timing generators
+
+	// Internal state
+	bool m_cur_closure;                             // Current internal closure state
+	u16 m_noise;                                    // 15-bit noise shift register
+	bool m_cur_noise;                               // Current noise output
+
+	// Filter coefficients and level histories
+	double m_voice_1[4];
+	double m_voice_2[4];
+	double m_voice_3[4];
+
+	double m_noise_1[3];
+	double m_noise_2[3];
+	double m_noise_3[2];
+	double m_noise_4[2];
+
+	double m_vn_1[4];
+	double m_vn_2[4];
+	double m_vn_3[4];
+	double m_vn_4[4];
+	double m_vn_5[2];
+	double m_vn_6[2];
+
+	double m_f1_a[4],  m_f1_b[4];                   // F1 filtering
+	double m_f2v_a[4], m_f2v_b[4];                  // F2 voice filtering
+	double m_f2n_a[2], m_f2n_b[2];                  // F2 noise filtering
+	double m_f3_a[4],  m_f3_b[4];                   // F3 filtering
+	double m_f4_a[4],  m_f4_b[4];                   // F4 filtering
+	double m_fx_a[1],  m_fx_b[2];                   // Final filtering
+	double m_fn_a[3],  m_fn_b[3];                   // Noise shaping
+
+	// Compute a total capacitor value based on which bits are currently active
+	static double bits_to_caps(u32 value, std::initializer_list<double> caps_values) {
+		double total = 0;
+		for(double d : caps_values) {
+			if(value & 1)
+				total += d;
+			value >>= 1;
+		}
+		return total;
+	}
+
+	// Shift a history of values by one and insert the new value at the front
+	template<u32 N> static void shift_hist(double val, double (&hist_array)[N]) {
+		for(u32 i=N-1; i>0; i--)
+			hist_array[i] = hist_array[i-1];
+		hist_array[0] = val;
+	}
+
+	// Apply a filter and compute the result. 'a' is applied to x (inputs) and 'b' to y (outputs)
+	template<u32 Nx, u32 Ny, u32 Na, u32 Nb> static double apply_filter(const double (&x)[Nx], const double (&y)[Ny], const double (&a)[Na], const double (&b)[Nb]) {
+		double total = 0;
+		for(u32 i=0; i<Na; i++)
+			total += x[i] * a[i];
+		for(u32 i=1; i<Nb; i++)
+			total -= y[i-1] * b[i];
+		return total / b[0];
+	}
+
+	void build_standard_filter(double *a, double *b,
+							   double c1t, // Unswitched cap, input, top
+							   double c1b, // Switched cap, input, bottom
+							   double c2t, // Unswitched cap, over first amp-op, top
+							   double c2b, // Switched cap, over first amp-op, bottom
+							   double c3,  // Cap between the two op-amps
+							   double c4); // Cap over second op-amp
+
+	void build_noise_shaper_filter(double *a, double *b,
+								   double c1,  // Cap over first amp-op
+								   double c2t, // Unswitched cap between amp-ops, input, top
+								   double c2b, // Switched cap between amp-ops, input, bottom
+								   double c3,  // Cap over second amp-op
+								   double c4); // Switched cap after second amp-op
+
+	void build_lowpass_filter(double *a, double *b,
+							  double c1t,  // Unswitched cap, over amp-op, top
+							  double c1b); // Switched cap, over amp-op, bottom
+
+	void build_injection_filter(double *a, double *b,
+								double c1b, // Switched cap, input, bottom
+								double c2t, // Unswitched cap, over first amp-op, top
+								double c2b, // Switched cap, over first amp-op, bottom
+								double c3,  // Cap between the two op-amps
+								double c4); // Cap over second op-amp
+
+
+	static void interpolate(u8 &reg, u8 target);    // Do one interpolation step
+	void chip_update();                             // Global update called at 20KHz (main/36)
+	void filters_commit(bool force);                // Commit the currently computed interpolation values to the filters
+	void phone_commit();                            // Commit the current phone id
+	stream_sample_t analog_calc();                  // Compute one more sample
 };
 
 
@@ -160,5 +190,4 @@ private:
 // device type definition
 extern const device_type VOTRAX_SC01;
 
-
-#endif /* __VOTRAX_H__ */
+#endif /* VOTRAX_H */
diff --git a/src/devices/video/ef9369.cpp b/src/devices/video/ef9369.cpp
new file mode 100644
index 0000000..7d97888
--- /dev/null
+++ b/src/devices/video/ef9369.cpp
@@ -0,0 +1,104 @@
+// license:GPL-2.0+
+// copyright-holders:Dirk Best
+/***************************************************************************
+
+    Thomson EF9369
+
+***************************************************************************/
+
+#include <algorithm>
+#include "ef9369.h"
+
+
+//**************************************************************************
+//  DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type EF9369 = &device_creator<ef9369_device>;
+
+
+//**************************************************************************
+//  LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+//  ef9369_device - constructor
+//-------------------------------------------------
+
+ef9369_device::ef9369_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+	: device_t(mconfig, EF9369, "EF9369 Single Chip Color Palette", tag, owner, clock, "ef9369", __FILE__),
+	m_address(0)
+{
+	std::fill(m_ca, m_ca + NUMCOLORS, 0);
+	std::fill(m_cb, m_cb + NUMCOLORS, 0);
+	std::fill(m_cc, m_cc + NUMCOLORS, 0);
+	std::fill(m_m, m_m + NUMCOLORS, 0);
+}
+
+//-------------------------------------------------
+//  device_start - device-specific startup
+//-------------------------------------------------
+
+void ef9369_device::device_start()
+{
+	// bind delegate
+	m_color_update_cb.bind_relative_to(*owner());
+
+	// register for save states
+	save_pointer(NAME(m_ca), NUMCOLORS);
+	save_pointer(NAME(m_cb), NUMCOLORS);
+	save_pointer(NAME(m_cc), NUMCOLORS);
+	save_pointer(NAME(m_m), NUMCOLORS);
+	save_item(NAME(m_address));
+}
+
+//-------------------------------------------------
+//  device_reset - device-specific reset
+//-------------------------------------------------
+
+void ef9369_device::device_reset()
+{
+	m_address = 0;
+}
+
+
+//**************************************************************************
+//  IMPLEMENTATION
+//**************************************************************************
+
+READ8_MEMBER( ef9369_device::data_r )
+{
+	if (m_address & 1)
+		return m_m[m_address >> 1] << 4 | m_cc[m_address >> 1];
+	else
+		return m_cb[m_address >> 1] << 4 | m_ca[m_address >> 1];
+}
+
+WRITE8_MEMBER( ef9369_device::data_w )
+{
+	const int entry = m_address >> 1;
+
+	if (m_address & 1)
+	{
+		m_m[entry] = (data >> 4) & 0x1;
+		m_cc[entry] = (data >> 0) & 0xf;
+	}
+	else
+	{
+		m_cb[entry] = (data >> 4) & 0xf;
+		m_ca[entry] = (data >> 0) & 0xf;
+	}
+
+	// update color
+	if (!m_color_update_cb.isnull())
+		m_color_update_cb(entry, m_m[entry], m_ca[entry], m_cb[entry], m_cc[entry]);
+
+	// auto-increment
+	m_address++;
+	m_address &= 0x1f;
+}
+
+WRITE8_MEMBER( ef9369_device::address_w )
+{
+	m_address = data & 0x1f;    // 5-bit
+}
diff --git a/src/devices/video/ef9369.h b/src/devices/video/ef9369.h
new file mode 100644
index 0000000..3689e8c
--- /dev/null
+++ b/src/devices/video/ef9369.h
@@ -0,0 +1,87 @@
+// license:GPL-2.0+
+// copyright-holders:Dirk Best
+/***************************************************************************
+
+    Thomson EF9369
+
+    Single Chip Color Palette
+
+               ___ ___
+      VSS   1 |*  u   | 28  HP
+     VDDC   2 |       | 27  P3
+      SMI   3 |       | 26  P2
+       CC   4 |       | 25  P1
+       CA   5 |       | 24  P0
+       CB   6 |       | 23  BLK
+        M   7 |       | 22  AS
+      AD0   8 |       | 21  R/W
+      VCC   9 |       | 20  DS
+    RESET  10 |       | 19  CS0
+      AD1  11 |       | 18  /CS
+      AD2  12 |       | 17  AD7
+      AD3  13 |       | 16  AD6
+      AD4  14 |_______| 15  AD5
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __EF9369_H__
+#define __EF9369_H__
+
+#include "emu.h"
+
+
+//**************************************************************************
+//  INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_EF9369_ADD(_tag) \
+	MCFG_DEVICE_ADD(_tag, EF9369, 0) \
+
+#define MCFG_EF9369_COLOR_UPDATE_CB(_class, _method) \
+	ef9369_device::set_color_update_callback(*device, ef9369_color_update_delegate(&_class::_method, #_class "::" #_method, downcast<_class *>(owner)));
+
+
+//**************************************************************************
+//  TYPE DEFINITIONS
+//**************************************************************************
+
+typedef device_delegate<void (int entry, bool m, uint8_t ca, uint8_t cb, uint8_t cc)> ef9369_color_update_delegate;
+#define EF9369_COLOR_UPDATE(name)   void name(int entry, bool m, uint8_t ca, uint8_t cb, uint8_t cc)
+
+// ======================> ef9369_device
+
+class ef9369_device : public device_t
+{
+public:
+	// construction/destruction
+	ef9369_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+	// configuration
+	static void set_color_update_callback(device_t &device, ef9369_color_update_delegate callback) { downcast<ef9369_device &>(device).m_color_update_cb = callback; }
+
+	DECLARE_READ8_MEMBER(data_r);
+	DECLARE_WRITE8_MEMBER(data_w);
+	DECLARE_WRITE8_MEMBER(address_w);
+
+	static const int NUMCOLORS = 16;
+
+protected:
+	// device-level overrides
+	virtual void device_start() override;
+	virtual void device_reset() override;
+
+private:
+	ef9369_color_update_delegate m_color_update_cb;
+
+	// state
+	uint8_t m_ca[NUMCOLORS], m_cb[NUMCOLORS], m_cc[NUMCOLORS];  // actually 4-bit
+	bool m_m[NUMCOLORS];
+	int m_address;
+};
+
+// device type definition
+extern const device_type EF9369;
+
+#endif // __EF9369_H__
diff --git a/src/devices/video/poly.h b/src/devices/video/poly.h
index d67e570..72706e0 100644
--- a/src/devices/video/poly.h
+++ b/src/devices/video/poly.h
@@ -130,6 +130,7 @@ public:
 	// getters
 	running_machine &machine() const { return m_machine; }
 	screen_device &screen() const { assert(m_screen != nullptr); return *m_screen; }
+	uint32_t triangles_drawn() const { return m_triangles; }
 
 	// synchronization
 	void wait(const char *debug_reason = "general");
diff --git a/src/devices/video/zeus2.cpp b/src/devices/video/zeus2.cpp
index 82951ee..45750a1 100644
--- a/src/devices/video/zeus2.cpp
+++ b/src/devices/video/zeus2.cpp
@@ -69,7 +69,7 @@ void zeus2_device::device_start()
 	/* allocate memory for "wave" RAM */
 	waveram = auto_alloc_array(machine(), uint32_t, WAVERAM0_WIDTH * WAVERAM0_HEIGHT * 8/4);
 	m_frameColor = std::make_unique<uint32_t[]>(WAVERAM1_WIDTH * WAVERAM1_HEIGHT * 2);
-	m_frameDepth = std::make_unique<uint16_t[]>(WAVERAM1_WIDTH * WAVERAM1_HEIGHT * 2);
+	m_frameDepth = std::make_unique<uint32_t[]>(WAVERAM1_WIDTH * WAVERAM1_HEIGHT * 2);
 
 	/* initialize polygon engine */
 	poly = auto_alloc(machine(), zeus2_renderer(this));
@@ -91,7 +91,7 @@ void zeus2_device::device_start()
 	/* save states */
 	save_pointer(NAME(waveram), WAVERAM0_WIDTH * WAVERAM0_HEIGHT * 2);
 	save_pointer(NAME(m_frameColor.get()), WAVERAM1_WIDTH * WAVERAM1_HEIGHT * 2);
-	save_pointer(NAME(m_frameDepth.get()), WAVERAM1_WIDTH * WAVERAM1_HEIGHT);
+	save_pointer(NAME(m_frameDepth.get()), WAVERAM1_WIDTH * WAVERAM1_HEIGHT * 2);
 	save_pointer(NAME(m_zeusbase), 0x80);
 	save_pointer(NAME(m_renderRegs), 0x50);
 	save_pointer(NAME(m_pal_table), 0x100);
@@ -117,6 +117,9 @@ void zeus2_device::device_reset()
 	memset(m_zeusbase, 0, sizeof(m_zeusbase[0]) * 0x80);
 	memset(m_renderRegs, 0, sizeof(m_renderRegs[0]) * 0x50);
 
+	m_curUCodeSrc = 0;
+	m_curPalTableSrc = 0;
+	m_palSize = 0;
 	zbase = 32.0f;
 	m_yScale = 0;
 	yoffs = 0x1dc000;
@@ -126,12 +129,6 @@ void zeus2_device::device_reset()
 	m_fill_color = 0;
 	m_fill_depth = 0;
 	m_renderAddr = 0;
-	m_directCmd = nullptr;
-
-	// Setup a linear pal conversion table for thegrid
-	for (int i = 0; i < 0x100; ++i) {
-		m_pal_table[i] = (i << 16) | (i << 8) | (i << 0);
-	}
 }
 #if DUMP_WAVE_RAM
 #include <iostream>
@@ -197,27 +194,26 @@ void zeus2_device::device_stop()
 uint32_t zeus2_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
 {
 	// Wait until configuration is completed before transfering anything
-	if (m_zeusbase[0x30] == 0)
+	if (!(m_zeusbase[0x10] & 0x20))
 		return 0;
 
 	int x, y;
 
 	poly->wait("SCREEN_UPDATE");
 
-	if (machine().input().code_pressed(KEYCODE_DOWN)) { zbase += machine().input().code_pressed(KEYCODE_LSHIFT) ? 0x10 : 1; popmessage("Zbase = %f", (double)zbase); }
-	if (machine().input().code_pressed(KEYCODE_UP)) { zbase -= machine().input().code_pressed(KEYCODE_LSHIFT) ? 0x10 : 1; popmessage("Zbase = %f", (double)zbase); }
+	//if (machine().input().code_pressed(KEYCODE_DOWN)) { zbase += machine().input().code_pressed(KEYCODE_LSHIFT) ? 0x10 : 1; popmessage("Zbase = %f", (double)zbase); }
+	//if (machine().input().code_pressed(KEYCODE_UP)) { zbase -= machine().input().code_pressed(KEYCODE_LSHIFT) ? 0x10 : 1; popmessage("Zbase = %f", (double)zbase); }
 
 	/* normal update case */
-	if (!machine().input().code_pressed(KEYCODE_W))
+	//if (!machine().input().code_pressed(KEYCODE_W))
+	if (1)
 	{
-		int xoffs = screen.visible_area().min_x;
 		for (y = cliprect.min_y; y <= cliprect.max_y; y++)
 		{
 			uint32_t *colorptr = &m_frameColor[frame_addr_from_xy(0, y, false)];
 			uint32_t *dest = &bitmap.pix32(y);
 			for (x = cliprect.min_x; x <= cliprect.max_x; x++) {
-				uint32_t bufX = x - xoffs;
-				dest[x] = colorptr[bufX];
+				dest[x] = colorptr[x];
 			}
 		}
 	}
@@ -402,48 +398,105 @@ void zeus2_device::zeus2_register_update(offs_t offset, uint32_t oldval, int log
 			int_timer->adjust(attotime::from_nsec(500));
 			break;
 
-		case 0x20:
-			/* toggles between two values based on the page:
-
-			    Page #      m_zeusbase[0x20]      m_zeusbase[0x38]
-			    ------      --------------      --------------
-			       0          $04000190           $00000000
-			       1          $04000000           $01900000
-			*/
-			zeus2_pointer_write(m_zeusbase[0x20] >> 24, (m_zeusbase[0x20] & 0xffffff), logit);
-			break;
-
-		case 0x30:
+		case 0x10:
+			// BITS 11 - 10 COL SIZE / BANK FOR WR1
+			// BITS 9 - 8   COL SIZE / BANK FOR WR0
+			if (logit) logerror("\tSys Setup");
+			if (m_zeusbase[0x10] & 0x20)
 			{
 				m_yScale = (((m_zeusbase[0x39] >> 16) & 0xfff) < 0x100) ? 0 : 1;
 				int hor = ((m_zeusbase[0x34] & 0xffff) - (m_zeusbase[0x33] >> 16)) << m_yScale;
 				int ver = ((m_zeusbase[0x35] & 0xffff) + 1) << m_yScale;
 				popmessage("reg[30]: %08X Screen: %dH X %dV yScale: %d", m_zeusbase[0x30], hor, ver, m_yScale);
-			}
-			m_screen->update_partial(m_screen->vpos());
-			{
 				int vtotal = (m_zeusbase[0x37] & 0xffff) << m_yScale;
 				int htotal = (m_zeusbase[0x34] >> 16) << m_yScale;
-				rectangle visarea((m_zeusbase[0x33] >> 16) << m_yScale, htotal - 1, 0, (m_zeusbase[0x35] & 0xffff) << m_yScale);
-				if (htotal > 0 && vtotal > 0 && visarea.min_x < visarea.max_x && visarea.max_y < vtotal)
-				{
-					m_screen->configure(htotal, vtotal, visarea, HZ_TO_ATTOSECONDS((double)ZEUS2_VIDEO_CLOCK / 4.0 / (htotal * vtotal)));
-					zeus_cliprect = visarea;
-					zeus_cliprect.max_x -= zeus_cliprect.min_x;
-					zeus_cliprect.min_x = 0;
-					// Startup vblank timer
-					vblank_timer->adjust(attotime::from_usec(1));
-				}
+				//rectangle visarea((m_zeusbase[0x33] >> 16) << m_yScale, htotal - 1, 0, (m_zeusbase[0x35] & 0xffff) << m_yScale);
+				rectangle visarea(0, hor-1, 0, ver-1);
+				m_screen->configure(htotal, vtotal, visarea, HZ_TO_ATTOSECONDS((double)ZEUS2_VIDEO_CLOCK / 4.0 / (htotal * vtotal)));
+				zeus_cliprect = visarea;
+				zeus_cliprect.max_x -= zeus_cliprect.min_x;
+				zeus_cliprect.min_x = 0;
+				// Startup vblank timer
+				vblank_timer->adjust(attotime::from_usec(1));
 			}
 			break;
 
+		case 0x11:
+			if (logit) logerror("\tHost Interface Setup");
+			break;
+
+		case 0x12:
+			if (logit) logerror("\tPLL Setup");
+			break;
+
+		case 0x13:
+			if (logit) logerror("\tZeus Test Out");
+			break;
+
+		case 0x20:
+			zeus2_pointer_write(m_zeusbase[0x20] >> 24, (m_zeusbase[0x20] & 0xffffff), logit);
+			break;
+
+		case 0x22:
+			if (logit) logerror("\tRend Setup 0");
+			break;
+
+		case 0x23:
+			if (logit) logerror("\tRend Setup 1");
+			break;
+
+		case 0x24:
+			// 0x601 == test mode
+			if (logit) logerror("\tRend Setup 4");
+			break;
+
+		case 0x2a:
+			// 0x000000c0 = bilenear off
+			if (logit) logerror("\tRend Force Off");
+			break;
+
+		case 0x2b:
+			if (logit) logerror("\tRend Force On");
+			break;
+
+		case 0x2c:
+			if (logit) logerror("\tRend AE Flag");
+			break;
+
+		case 0x2d:
+			if (logit) logerror("\tRend AF Flag");
+			break;
+
+		case 0x2f:
+			if (logit) logerror("\tPixel Proc Setup");
+			break;
+
+
+		case 0x30:
+			if (logit) logerror("\tCRT Controller Setup = %08X", m_zeusbase[offset]);
+			break;
+
+		case 0x31:
+			if (logit) logerror("\tDotClk Sel 1 : DotClk Sel 2 = %08X", m_zeusbase[offset]);
+			break;
+		case 0x32:
+			if (logit) logerror("\tHSync End = %i HSync Start = %i", (m_zeusbase[offset] >> 16), m_zeusbase[offset] & 0xffff);
+			break;
 		case 0x33:
+			if (logit) logerror("\tHBlank End = %i Update Start = %i", (m_zeusbase[offset] >> 16), m_zeusbase[offset] & 0xffff);
+			break;
 		case 0x34:
+			if (logit) logerror("\tHTotal = %i HBlank Start = %i", (m_zeusbase[offset] >> 16), m_zeusbase[offset] & 0xffff);
+			break;
 		case 0x35:
+			if (logit) logerror("\tVSync Start = %i VBlank Start = %i", (m_zeusbase[offset] >> 16), m_zeusbase[offset] & 0xffff);
+			break;
 		case 0x36:
+			if (logit) logerror("\tVTotal = %i VSync End = %i", (m_zeusbase[offset] >> 16), m_zeusbase[offset] & 0xffff);
+			break;
 		case 0x37:
+			if (logit) logerror("\tVTotal = %i", m_zeusbase[offset]);
 			break;
-
 		case 0x38:
 			{
 				uint32_t temp = m_zeusbase[0x38];
@@ -454,52 +507,55 @@ void zeus2_device::zeus2_register_update(offs_t offset, uint32_t oldval, int log
 				m_zeusbase[0x38] = temp;
 			}
 			break;
+		case 0x39:
+			if (logit) logerror("\tLine Length = %i FIFO AF = %i FIFO AE = %i", (m_zeusbase[offset] >> 16) & 0xfff, (m_zeusbase[offset] >> 8) & 0xff, m_zeusbase[offset] & 0xff);
+			break;
 
 		case 0x40:
-			/* in direct mode it latches values */
-			if ((m_zeusbase[0x4e] & 0x20) && m_zeusbase[0x40] == 0x00820000)
-			{
-				const void *src = waveram0_ptr_from_expanded_addr(m_zeusbase[0x41]);
-				m_zeusbase[0x48] = WAVERAM_READ32(src, 0);
-				m_zeusbase[0x49] = WAVERAM_READ32(src, 1);
-
-				if (m_zeusbase[0x4e] & 0x40)
+		{
+			int code = (m_zeusbase[0x40] >> 16) & 0xf;
+			if (code == 0x2) {
+				/* in direct mode it latches values */
+				if ((m_zeusbase[0x4e] & 0x20))
 				{
-					m_zeusbase[0x41]++;
-					m_zeusbase[0x41] += (m_zeusbase[0x41] & 0x400) << 6;
-					m_zeusbase[0x41] &= ~0xfc00;
+					const void *src = waveram0_ptr_from_expanded_addr(m_zeusbase[0x41]);
+					m_zeusbase[0x48] = WAVERAM_READ32(src, 0);
+					m_zeusbase[0x49] = WAVERAM_READ32(src, 1);
+
+					if (m_zeusbase[0x4e] & 0x40)
+					{
+						m_zeusbase[0x41]++;
+						m_zeusbase[0x41] += (m_zeusbase[0x41] & 0x400) << 6;
+						m_zeusbase[0x41] &= ~0xfc00;
+					}
 				}
 			}
-			// mwskinsa 0xE085001F -- pal 555?
-			// thegrid 0x0055002C ???
-			// crusnexo 0x005500FF ???
-			// crusnexo 0x00A20000 ???
-			// Zeus render info
-			if ((m_zeusbase[0x40] >> 16) == 0xc085) {
-				if (logit)
-					logerror("\t-- pal table argb32 load: control: %08X addr: %08X", m_zeusbase[0x40], m_zeusbase[0x41]);
-				// Load pal table from ARGB32
-				poly->wait("PAL_TABLE_WRITE");
-				void *dataPtr = waveram0_ptr_from_expanded_addr(m_zeusbase[0x41]);
-				load_pal_table(dataPtr, m_zeusbase[0x40], logit);
-			} else if ((m_zeusbase[0x40] >> 16) == 0x0084) {
+			else if (code == 0x4) {
 				// Load pal table from RGB555
-				poly->wait("PAL_TABLE_WRITE");
-				void *dataPtr = waveram0_ptr_from_expanded_addr(m_zeusbase[0x41]);
-				load_pal_table(dataPtr, m_zeusbase[0x40], logit);
 				if (logit)
 					logerror("\t-- pal table rgb555 load: control: %08X addr: %08X", m_zeusbase[0x40], m_zeusbase[0x41]);
+				poly->wait("PAL_TABLE_WRITE");
+				m_curPalTableSrc = m_zeusbase[0x41];
+				void *dataPtr = waveram0_ptr_from_expanded_addr(m_zeusbase[0x41]);
+				load_pal_table(dataPtr, m_zeusbase[0x40], 0, logit);
 			}
-			else if ((((m_zeusbase[0x40] >> 24) & 0xff) == 0x38) ||
-				(((m_zeusbase[0x40] >> 24) & 0xff) == 0x2d)) {
-				// Direct command buffer
-				m_directCmd = (uint32_t*)waveram0_ptr_from_expanded_addr(m_zeusbase[0x41]);
+			else if (code == 0x5) {
+				// Zeus microcode burst from waveram
 				if (logit)
-					logerror("\t-- direct cmd: %08X addr: %08X", m_zeusbase[0x40], m_zeusbase[0x41]);
-				{
+					logerror("\t-- ucode load: control: %08X addr: %08X", m_zeusbase[0x40], m_zeusbase[0x41]);
+				// Load ucode from waveram
+				poly->wait("UCODE_LOAD");
+				void *dataPtr = waveram0_ptr_from_expanded_addr(m_zeusbase[0x41]);
+				load_ucode(dataPtr, m_zeusbase[0x40], logit);
+				if (((m_zeusbase[0x40] >> 24) & 0xff) >= 0xc0) {
+					// Light table load
+					if (logit) logerror("\t-- light table loaded");
+				}
+				else {
+					m_curUCodeSrc = m_zeusbase[0x41];
 					// Zeus Quad Size
 					switch (m_zeusbase[0x40]) {
-					case 0x38550083: case 0x3885007B: case 0x2D550083:
+					case 0x38550083: case 0x2D550083: case 0x3885007B:
 						zeus_quad_size = 14;
 						break;
 					case 0x3855006F: case 0x38550088: case 0x388500A9:
@@ -515,13 +571,13 @@ void zeus2_device::zeus2_register_update(offs_t offset, uint32_t oldval, int log
 						zeus_quad_size = 10;
 						break;
 					default:
-						logerror("default quad size 10\n");
+						logerror(" default quad size 10\n");
 						zeus_quad_size = 10;
 						break;
 					}
 				}
 				if (1 && logit) {
-					uint32_t *wavePtr = (uint32_t*)WAVERAM_BLOCK0(m_zeusbase[0x41]);
+					uint32_t *wavePtr = (uint32_t*)waveram0_ptr_from_expanded_addr(m_zeusbase[0x41]);
 					uint32_t waveData;
 					int size = m_zeusbase[0x40] & 0xff;
 					logerror("\n Setup size=%d [40]=%08X [41]=%08X [4e]=%08X\n", zeus_quad_size, m_zeusbase[0x40], m_zeusbase[0x41], m_zeusbase[0x4e]);
@@ -536,7 +592,15 @@ void zeus2_device::zeus2_register_update(offs_t offset, uint32_t oldval, int log
 					logerror("\n");
 				}
 			}
-			break;
+			else if (code == 0x6) {
+				// Zeus model fifo burst from waveram
+			}
+			else {
+				if (logit)
+					logerror("\t-- unknown burst: control: %08X addr: %08X", m_zeusbase[0x40], m_zeusbase[0x41]);
+			}
+		}
+		break;
 		case 0x41:
 			/* this is the address, except in read mode, where it latches values */
 			if (m_zeusbase[0x4e] & 0x10)
@@ -593,64 +657,67 @@ void zeus2_device::zeus2_register_update(offs_t offset, uint32_t oldval, int log
 			break;
 
 		case 0x50:
-			if (m_zeusbase[0x50] == 0x00510000) {
-				// SGRAM Special Mode Register Write
-				if (m_zeusbase[0x51] == 0x00200000) {
-					// SGRAM Mask Register
-					if ((m_zeusbase[0x58] & m_zeusbase[0x59] & m_zeusbase[0x5a]) != 0xffffffff)
-						logerror("zeus2_register_update: Warning! Mask Register not equal to 0xffffffff\n");
-				}
-				if (m_zeusbase[0x51] == 0x00400000) {
-					// SGRAM Color Register
-					m_fill_color = m_zeusbase[0x58];
-					m_fill_depth = m_zeusbase[0x5a];
-					if (m_zeusbase[0x58] != m_zeusbase[0x59])
-						logerror("zeus2_register_update: Warning! Different fill colors are set.\n");
-				}
-			}
-			//else if (1 && ((m_zeusbase[0x50] & 0x000f0000)==0x80000) && (m_zeusbase[0x50] & 0xffff)) {
-			else if ((m_zeusbase[0x50] &  0x80000) && (m_zeusbase[0x50] & 0xffff)) {
-				// Fast fill
-				// Unknown what the exact bit fields are, this is a just a guess
-				// Atlantis: 0x00983FFF => clear entire frame buffer, 0x00981FFF => clear one frame
-				// crusnexo: 0x007831FF => clear one frame
-				// thegrid:  0x008831FF => clear one frame
-				// thegrid:  0x0079FFFF => clear entire frame buffer at 51=0 then 51=00800000, only seen at initial tests in thegrid
-				uint32_t addr = frame_addr_from_phys_addr(m_zeusbase[0x51]);
-				uint32_t numBytes = (m_zeusbase[0x50] & 0xffff) + 1;
-				numBytes *= 0x40;
-				if (m_zeusbase[0x50] & 0x10000) {
-					addr = 0x0;
-					numBytes = WAVERAM1_WIDTH * WAVERAM1_HEIGHT * 8;
-					//printf("Clearing buffer: numBytes: %08X addr: %08X reg50: %08X\n", numBytes, addr, m_zeusbase[0x50]);
+			{
+				int code = (m_zeusbase[0x50] >> 16) & 0xf;
+
+				if (code == 0x1) {
+					// SGRAM Special Mode Register Write
+					if (m_zeusbase[0x51] == 0x00200000) {
+						// SGRAM Mask Register
+						if ((m_zeusbase[0x58] & m_zeusbase[0x59] & m_zeusbase[0x5a]) != 0xffffffff)
+							logerror("zeus2_register_update: Warning! Mask Register not equal to 0xffffffff\n");
+					}
+					if (m_zeusbase[0x51] == 0x00400000) {
+						// SGRAM Color Register
+						m_fill_color = m_zeusbase[0x58];
+						m_fill_depth = ((m_zeusbase[0x5a] & 0xffff) << 16) | ((m_zeusbase[0x58] >> 24) << 8);
+						m_fill_depth >>= 8;  // Sign extend down to 24 bits
+						if (m_zeusbase[0x58] != m_zeusbase[0x59])
+							logerror("zeus2_register_update: Warning! Different fill colors are set.\n");
+					}
 				}
-				if (logit)
-					logerror(" -- Clearing buffer: numBytes: %08X addr: %08X reg51: %08X", numBytes, addr, m_zeusbase[0x51]);
-				memset(&m_frameColor[addr], m_fill_color, numBytes);
-				memset(&m_frameDepth[addr], m_fill_depth, numBytes/2);
-			}
-			else if ((m_zeusbase[0x5e] >> 16) != 0xf208 && !(m_zeusbase[0x5e] & 0xffff)) {
-			/* If 0x5e==0xf20a0000 (atlantis) or 0xf20d0000 (the grid) then process the read/write now */
-				/*
-				m_zeusbase[0x5e]:
-				bit 0-1: which register triggers write through
-				bit 3:   enable write through via these registers
-				bit 4:   seems to be set during reads, when 0x51 is used for latching
-				bit 5:   unknown, currently used to specify ordering, but this is suspect
-				bit 6:   enable autoincrement on write through
-				*/
-				//if (m_zeusbase[0x50] == 0x00890000)
-				if ((m_zeusbase[0x50] == 0x00890000) || (m_zeusbase[0x50] == 0x00e90000))
-				{
-					frame_write();
+				else if (code == 0x8) {
+					// Fast fill
+					// Unknown what the exact bit fields are, this is a just a guess
+					// Atlantis: 0x00983FFF => clear entire frame buffer, 0x00981FFF => clear one frame
+					// crusnexo: 0x007831FF => clear one frame
+					// thegrid:  0x008831FF => clear one frame
+					// thegrid:  0x0079FFFF => clear entire frame buffer at 51=0 then 51=00800000, only seen at initial tests in thegrid
+					uint32_t addr = frame_addr_from_phys_addr(m_zeusbase[0x51]);
+					uint32_t numBytes = (m_zeusbase[0x50] & 0xffff) + 1;
+					numBytes *= 0x40;
+					if (m_zeusbase[0x50] & 0x10000) {
+						addr = 0x0;
+						numBytes = WAVERAM1_WIDTH * WAVERAM1_HEIGHT * 8;
+						//printf("Clearing buffer: numBytes: %08X addr: %08X reg50: %08X\n", numBytes, addr, m_zeusbase[0x50]);
+					}
+					if (logit)
+						logerror(" -- Clearing buffer: numBytes: %08X addr: %08X reg51: %08X", numBytes, addr, m_zeusbase[0x51]);
+					memset(&m_frameColor[addr], m_fill_color, numBytes);
+					memset(&m_frameDepth[addr], m_fill_depth, numBytes);
 				}
-				else if (m_zeusbase[0x50] == 0x00720000) {
-					/* Do the read */
-					frame_read();
+				else if ((m_zeusbase[0x5e] >> 16) != 0xf208 && !(m_zeusbase[0x5e] & 0xffff)) {
+					/* If 0x5e==0xf20a0000 (atlantis) or 0xf20d0000 (the grid) then process the read/write now */
+						/*
+						m_zeusbase[0x5e]:
+						bit 0-1: which register triggers write through
+						bit 3:   enable write through via these registers
+						bit 4:   seems to be set during reads, when 0x51 is used for latching
+						bit 5:   unknown, currently used to specify ordering, but this is suspect
+						bit 6:   enable autoincrement on write through
+						*/
+					if (code == 0x9)
+					{
+						frame_write();
+					}
+					else if (code == 0x2) {
+						/* Do the read */
+						frame_read();
+					}
+					/* make sure we log anything else */
+					//else if (logit || m_zeusbase[0x50] != 0x0)
+					//  logerror("\tw[50]=%08X [5E]=%08X\n", m_zeusbase[0x50], m_zeusbase[0x5e]);
 				}
-				/* make sure we log anything else */
-				else if (logit || m_zeusbase[0x50] != 0x0)
-					logerror("\tw[50]=%08X [5E]=%08X\n", m_zeusbase[0x50], m_zeusbase[0x5e]);
 			}
 			break;
 		case 0x51:
@@ -711,10 +778,96 @@ void zeus2_device::zeus2_register_update(offs_t offset, uint32_t oldval, int log
 					logerror("\t[50]=%08X [5E]=%08X", m_zeusbase[0x50], m_zeusbase[0x5e]);
 			break;
 
-		case 0x63: case 0x6a: case 0x6b:
-		case 0x76: case 0x77:
+		// 0x60, 0x61, 0x62 Translation matrix, set using fifo command
+
+		case 0x63:
+			if (logit)
+				logerror("\tMAC Trans3 HSR Correction Factor = %8.2f", reinterpret_cast<float&>(m_zeusbase[offset]));
+			break;
+
+		case 0x64:
+			if (logit)
+				logerror("\tMAC Offset");
+			break;
+
+		case 0x65:
+			if (logit)
+				logerror("\tMAC Offset");
+			break;
+
+		case 0x66:
 			if (logit)
-				logerror("\tfloatIEEE754 = %8.2f", reinterpret_cast<float&>(m_zeusbase[offset]));
+				logerror("\tMultiply Offset");
+			break;
+
+		case 0x67:
+			if (logit)
+				logerror("\tMath MAC Setup");
+			break;
+
+		case 0x68:
+			if (logit)
+				logerror("\tALU Float Offset");
+			break;
+
+		case 0x6A:
+			if (logit)
+				logerror("\tALU RegC X_OFF = %8.2f", reinterpret_cast<float&>(m_zeusbase[offset]));
+			break;
+
+		case 0x6B:
+			if (logit)
+				logerror("\tALU RegD Y_OFF = %8.2f", reinterpret_cast<float&>(m_zeusbase[offset]));
+			break;
+
+		case 0x6c:
+			if (logit)
+				logerror("\tALU Inv Offset");
+			break;
+
+		case 0x6f:
+			if (logit)
+				logerror("\tLight Table Setup");
+			break;
+
+		case 0x76:
+			if (logit)
+				logerror("\tMath Comp Reg0 XClip = %8.2f", reinterpret_cast<float&>(m_zeusbase[offset]));
+			break;
+
+		case 0x77:
+			if (logit)
+				logerror("\tMath Comp Reg1 YClip = %8.2f", reinterpret_cast<float&>(m_zeusbase[offset]));
+			break;
+
+		case 0x78:
+			if (logit)
+				logerror("\tMath Comp Reg2 ZClip = %8.2f", reinterpret_cast<float&>(m_zeusbase[offset]));
+			break;
+
+		case 0x79:
+			if (logit)
+				logerror("\tMath Comp Reg3 YRange = %8.2f", reinterpret_cast<float&>(m_zeusbase[offset]));
+			break;
+
+		case 0x7a:
+			if (logit)
+				logerror("\tMath Conditional Branch Setup");
+			break;
+
+		case 0x7c:
+			if (logit)
+				logerror("\tMath Compare Setup 1");
+			break;
+
+		case 0x7D:
+			if (logit)
+				logerror("\tMath FIFO AF / AE Input FIFO AF / AE");
+			break;
+
+		case 0x7f:
+			if (logit)
+				logerror("\tMath Setup Reg");
 			break;
 
 	}
@@ -725,12 +878,13 @@ void zeus2_device::zeus2_register_update(offs_t offset, uint32_t oldval, int log
 /*************************************
 *  Load pal table from waveram
 *************************************/
-void zeus2_device::load_pal_table(void *wavePtr, uint32_t ctrl, int logit)
+void zeus2_device::load_pal_table(void *wavePtr, uint32_t ctrl, int type, int logit)
 {
-	uint32_t *tablePtr = m_pal_table;
-	int count = ctrl & 0xff;
-	uint32_t cmd = ctrl >> 24;
-	if (cmd == 0x0) {
+	int count = ctrl & 0xffff;
+	m_palSize = (count + 1) * 4;
+	uint32_t addr = (ctrl >> 24) << 1;
+	uint32_t *tablePtr = &m_pal_table[addr];
+	if (type == 0) {
 		// Convert from RGB555
 		uint16_t *src = (uint16_t*)wavePtr;
 		for (int i = 0; i <= count; ++i) {
@@ -739,14 +893,39 @@ void zeus2_device::load_pal_table(void *wavePtr, uint32_t ctrl, int logit)
 			*tablePtr++ = conv_rgb555_to_rgb32(*src++);
 			*tablePtr++ = conv_rgb555_to_rgb32(*src++);
 		}
-	} else if (cmd==0xc0) {
-		// The data seems to be in ARGB32 format
+	}
+	else {
+		// Raw Copy
 		uint32_t *src = (uint32_t*)wavePtr;
 		for (int i = 0; i <= count; ++i) {
 			*tablePtr++ = *src++;
 			*tablePtr++ = *src++;
 		}
 	}
+	if (logit) {
+		logerror("\ntable: ");
+		tablePtr = &m_pal_table[addr];
+		for (int i = 0; i <= count*4; ++i) {
+			logerror(" %08X", *tablePtr++);
+			if (0 && (i + 1) % 16 == 0)
+				logerror("\n");
+		}
+		logerror("\n");
+	}
+}
+/*************************************
+*  Load microcode from waveram
+*************************************/
+void zeus2_device::load_ucode(void *wavePtr, uint32_t ctrl, int logit)
+{
+	int count = ctrl & 0xffff;
+	uint32_t addr = (ctrl >> 24) << 1;
+	uint32_t *src = (uint32_t*)wavePtr;
+	uint32_t *tablePtr = &m_ucode[addr];
+	for (int i = 0; i <= count; ++i) {
+		*tablePtr++ = *src++;
+		*tablePtr++ = *src++;
+	}
 }
 
 /*************************************
@@ -780,20 +959,30 @@ if (subregdata_count[which] < 256)
 
 	switch (which)
 	{
-		case 0x40:
+		case 0x01:
+			// Limit to 12 bits
+			m_renderRegs[which] &= 0xfff;
+			zeus_cliprect.max_x = m_renderRegs[which];
 			if (logit)
-				logerror("\t(R%02X) = %06x Render Unknown", which, value);
+				logerror("\t(R%02X) = %4i Rend XClip", which & 0xfff, value);
 			break;
 
-		case 0xff:
-			// Reset???
+		case 0x02:
+			// Limit to 12 bits
+			m_renderRegs[which] &= 0xfff;
+			zeus_cliprect.max_y = m_renderRegs[which];
+			if (logit)
+				logerror("\t(R%02X) = %4i Rend YClip", which & 0xfff, value);
+			break;
+
+		case 0x03:
 			if (logit)
-				logerror("\tRender Reset");
+				logerror("\t(R%02X) = %06x Rend XOffset", which, value);
 			break;
 
 		case 0x04:
 			if (logit)
-				logerror("\t(R%02X) = %06x Render Loc", which, value);
+				logerror("\t(R%02X) = %06x Rend YOffset", which, value);
 			break;
 
 		case 0x05:
@@ -802,9 +991,73 @@ if (subregdata_count[which] < 256)
 				logerror("\t(R%02X)  texbase = %06x", which, zeus_texbase);
 			break;
 
-		default:
+		case 0x07:
 			if (logit)
-				logerror("\t(R%02X) = %06x", which, value);
+				logerror("\t(R%02X)  Texel Mask = %06x", which, value);
+			break;
+
+		case 0x08:
+			{
+				//int blockNum = ((m_renderRegs[0x9] >> 16) * 1024 + (m_renderRegs[0x9] & 0xffff));
+				int blockNum = m_renderRegs[0x9];
+				void *dataPtr = (void *)(&waveram[blockNum * 2]);
+				if (logit)
+					logerror("\t(R%02X) = %06x PAL Control Load Table Byte Addr = %08X", which, value, blockNum * 8);
+				m_curPalTableSrc = m_renderRegs[0x9];
+				load_pal_table(dataPtr, m_renderRegs[0x8], 0, logit);
+			}
+			break;
+
+		case 0x09:
+			if (logit) logerror("\t(R%02X) = %06x PAL Addr", which, value);
+			break;
+
+		case 0x0a:
+			if (logit) logerror("\t(R%02X) = %4i Pixel ALU IntA", which, value);
+			break;
+
+		case 0x0b:
+			if (logit) logerror("\t(R%02X) = %4i Pixel ALU IntB", which, value);
+			break;
+
+		case 0x0c:
+			if (logit) logerror("\t(R%02X) = %4i Pixel ALU IntC (Translucency FG)", which, value);
+			break;
+
+		case 0x0d:
+			if (logit) logerror("\t(R%02X) = %4i Pixel ALU IntD (Translucency BG)", which, value);
+			break;
+
+		case 0x11:
+			if (logit) logerror("\t(R%02X)  Texel Setup = %06x", which, value);
+			break;
+
+		case 0x12:
+			if (logit) logerror("\t(R%02X)  Pixel FIFO Setup = %06x", which, value);
+			break;
+
+		case 0x14:
+			if (logit) logerror("\t(R%02X) = %06x ZBuf Control", which, value);
+			break;
+
+		case 0x15:
+			m_zbufmin = int32_t((value & 0xffffff) << 8) >> 8;
+			if (logit) logerror("\t(R%02X) = %d ZBuf Min", which, m_zbufmin / 4096.0f);
+			break;
+
+		case 0x40:
+			// 0x004000 no shading
+			// 0x024004 gouraud shading
+			if (logit) logerror("\t(R%02X) = %06x Pixel ALU Control", which, value);
+			break;
+
+		case 0xff:
+			// Reset???
+			if (logit) logerror("\tRender Reset");
+			break;
+
+		default:
+			if (logit) logerror("\t(R%02X) = %06x", which, value);
 			break;
 
 
@@ -856,6 +1109,7 @@ bool zeus2_device::zeus2_fifo_process(const uint32_t *data, int numwords)
 		case 0x08:
 			if (numwords < 14)
 				return false;
+			zeus2_register32_w(0x63, data[1], log_fifo);
 			dataoffs = 1;
 
 		/* 0x07: set matrix and point (crusnexo) */
@@ -892,10 +1146,10 @@ bool zeus2_device::zeus2_fifo_process(const uint32_t *data, int numwords)
 			}
 			break;
 
-		// 0x14: ?? atlantis
 		/* 0x15: set point only (thegrid) */
 		/* 0x16: set point only (crusnexo) */
-		case 0x14:
+		// 0x10: atlantis
+		case 0x10:
 		case 0x15:
 		case 0x16:
 			if (numwords < 4)
@@ -917,18 +1171,18 @@ bool zeus2_device::zeus2_fifo_process(const uint32_t *data, int numwords)
 			break;
 
 		// 0x1c: thegrid (3 words)
+		// 0x14: atlantis
+		case 0x14:
 		case 0x1c:
 			if (m_thegrid) {
 				if (numwords < 3)
 					return false;
 				if (log_fifo)
-					log_fifo_command(data, numwords, " -- unknown control\n");
+					log_fifo_command(data, numwords, " -- Init light source\n");
 				break;
 			}
 		// 0x1b: thegrid
 		// 0x1c: crusnexo (4 words)
-		// 0x10: atlantis???
-		case 0x10:
 		case 0x1b:
 			if (numwords < 4)
 				return false;
@@ -1034,7 +1288,7 @@ void zeus2_device::zeus2_draw_model(uint32_t baseaddr, uint16_t count, int logit
 	uint32_t texdata = 0;
 
 	if (logit)
-		logerror(" -- model @ %08X, len %04X\n", baseaddr, count);
+		logerror(" -- model @ %08X, len %04X, palSrc %08x, rendSrc %08x\n", baseaddr, count, m_curPalTableSrc, m_curUCodeSrc);
 
 	if (count > 0xc800)
 		fatalerror("Extreme count\n");
@@ -1202,11 +1456,11 @@ void zeus2_renderer::zeus2_draw_quad(const uint32_t *databuffer, uint32_t texdat
 	if (logit)
 		m_state->logerror("quad %d\n", m_state->zeus_quad_size);
 
-	if (machine().input().code_pressed(KEYCODE_Q) && (m_state->m_renderRegs[0x5] != 0x1fdf00)) return;
-	if (machine().input().code_pressed(KEYCODE_E) && (m_state->m_renderRegs[0x5] != 0x07f540)) return;
-	if (machine().input().code_pressed(KEYCODE_R) && (m_state->m_renderRegs[0x5] != 0x081580)) return;
-	if (machine().input().code_pressed(KEYCODE_T) && (m_state->m_renderRegs[0x5] != 0x14db00)) return;
-	if (machine().input().code_pressed(KEYCODE_Y) && (m_state->m_renderRegs[0x5] != 0x14d880)) return;
+	//if (machine().input().code_pressed(KEYCODE_Q) && (m_state->m_renderRegs[0x5] != 0x1fdf00)) return;
+	//if (machine().input().code_pressed(KEYCODE_E) && (m_state->m_renderRegs[0x5] != 0x07f540)) return;
+	//if (machine().input().code_pressed(KEYCODE_R) && (m_state->m_renderRegs[0x5] != 0x081580)) return;
+	//if (machine().input().code_pressed(KEYCODE_T) && (m_state->m_renderRegs[0x5] != 0x14db00)) return;
+	//if (machine().input().code_pressed(KEYCODE_Y) && (m_state->m_renderRegs[0x5] != 0x14d880)) return;
 	//if (machine().input().code_pressed(KEYCODE_Q) && (texdata & 0xffff) == 0x119) return;
 	//if (machine().input().code_pressed(KEYCODE_E) && (texdata & 0xffff) == 0x01d) return;
 	//if (machine().input().code_pressed(KEYCODE_R) && (texdata & 0xffff) == 0x11d) return;
@@ -1265,52 +1519,52 @@ void zeus2_renderer::zeus2_draw_quad(const uint32_t *databuffer, uint32_t texdat
 		vert[0].x = (int16_t)databuffer[2];
 		vert[0].y = (int16_t)databuffer[3];
 		vert[0].p[0] = (int16_t)databuffer[4];
-		vert[0].p[1] = (databuffer[5] >> 0) & 0xff;
-		vert[0].p[2] = (databuffer[5] >> 8) & 0xff;
+		vert[0].p[1] = ((databuffer[5] >> 0) & 0xff) << 2;
+		vert[0].p[2] = ((databuffer[5] >> 8) & 0xff) << 2;
 
 		vert[1].x = (int16_t)(databuffer[2] >> 16);
 		vert[1].y = (int16_t)(databuffer[3] >> 16);
 		vert[1].p[0] = (int16_t)(databuffer[4] >> 16);
-		vert[1].p[1] = (databuffer[5] >> 16) & 0xff;
-		vert[1].p[2] = (databuffer[5] >> 24) & 0xff;
+		vert[1].p[1] = ((databuffer[5] >> 16) & 0xff) << 2;
+		vert[1].p[2] = ((databuffer[5] >> 24) & 0xff) << 2;
 
 		vert[2].x = (int16_t)databuffer[6];
 		vert[2].y = (int16_t)databuffer[7];
 		vert[2].p[0] = (int16_t)databuffer[8];
-		vert[2].p[1] = (databuffer[9] >> 0) & 0xff;
-		vert[2].p[2] = (databuffer[9] >> 8) & 0xff;
+		vert[2].p[1] = ((databuffer[9] >> 0) & 0xff) << 2;
+		vert[2].p[2] = ((databuffer[9] >> 8) & 0xff) << 2;
 
 		vert[3].x = (int16_t)(databuffer[6] >> 16);
 		vert[3].y = (int16_t)(databuffer[7] >> 16);
 		vert[3].p[0] = (int16_t)(databuffer[8] >> 16);
-		vert[3].p[1] = (databuffer[9] >> 16) & 0xff;
-		vert[3].p[2] = (databuffer[9] >> 24) & 0xff;
+		vert[3].p[1] = ((databuffer[9] >> 16) & 0xff) << 2;
+		vert[3].p[2] = ((databuffer[9] >> 24) & 0xff) << 2;
 	}
 	else {
 		//printf("R40: %06X\n", m_state->m_renderRegs[0x40]);
 		vert[0].x = (int16_t)databuffer[2];
 		vert[0].y = (int16_t)databuffer[3];
 		vert[0].p[0] = (int16_t)databuffer[6];
-		vert[0].p[1] = (databuffer[1] >> 2) & 0xff;
-		vert[0].p[2] = (databuffer[1] >> 18) & 0xff;
+		vert[0].p[1] = (databuffer[1] >> 0) & 0x3ff;
+		vert[0].p[2] = (databuffer[1] >> 16) & 0x3ff;
 
 		vert[1].x = (int16_t)(databuffer[2] >> 16);
 		vert[1].y = (int16_t)(databuffer[3] >> 16);
 		vert[1].p[0] = (int16_t)(databuffer[6] >> 16);
-		vert[1].p[1] = (databuffer[4] >> 2) & 0xff;
-		vert[1].p[2] = (databuffer[4] >> 12) & 0xff;
+		vert[1].p[1] = (databuffer[4] >> 0) & 0x3ff;
+		vert[1].p[2] = (databuffer[4] >> 10) & 0x3ff;
 
 		vert[2].x = (int16_t)databuffer[8];
 		vert[2].y = (int16_t)databuffer[9];
 		vert[2].p[0] = (int16_t)databuffer[7];
-		vert[2].p[1] = (databuffer[4] >> 22) & 0xff;
-		vert[2].p[2] = (databuffer[5] >> 2) & 0xff;
+		vert[2].p[1] = (databuffer[4] >> 20) & 0x3ff;
+		vert[2].p[2] = (databuffer[5] >> 0) & 0x3ff;
 
 		vert[3].x = (int16_t)(databuffer[8] >> 16);
 		vert[3].y = (int16_t)(databuffer[9] >> 16);
 		vert[3].p[0] = (int16_t)(databuffer[7] >> 16);
-		vert[3].p[1] = (databuffer[5] >> 12) & 0xff;
-		vert[3].p[2] = (databuffer[5] >> 22) & 0xff;
+		vert[3].p[1] = (databuffer[5] >> 10) & 0x3ff;
+		vert[3].p[2] = (databuffer[5] >> 20) & 0x3ff;
 	}
 	int unknown[8];
 	float unknownFloat[4];
@@ -1358,20 +1612,18 @@ void zeus2_renderer::zeus2_draw_quad(const uint32_t *databuffer, uint32_t texdat
 
 	int logextra = 1;
 
-	//float xScale = 1.0f / 8.0f;
-	//float yScale = 1.0f / 8.0f;
-	//float zScale = 1.0f / 8.0f;
+	int intScale = m_state->m_zeusbase[0x66] - 0x8e;
+	float fScale = pow(2.0f, intScale);
 	for (i = 0; i < 4; i++)
 	{
 		float x = vert[i].x;
 		float y = vert[i].y;
 		float z = vert[i].p[0];
-		//if (0) {
-		//  x *= xScale;
-		//  y *= yScale;
-		//  z *= zScale;
-
-		//}
+		if (1) {
+		  x *= fScale;
+		  y *= fScale;
+		  z *= fScale;
+		}
 		vert[i].x = x * m_state->zeus_matrix[0][0] + y * m_state->zeus_matrix[0][1] + z * m_state->zeus_matrix[0][2];
 		vert[i].y = x * m_state->zeus_matrix[1][0] + y * m_state->zeus_matrix[1][1] + z * m_state->zeus_matrix[1][2];
 		vert[i].p[0] = x * m_state->zeus_matrix[2][0] + y * m_state->zeus_matrix[2][1] + z * m_state->zeus_matrix[2][2];
@@ -1381,17 +1633,20 @@ void zeus2_renderer::zeus2_draw_quad(const uint32_t *databuffer, uint32_t texdat
 			vert[i].y += m_state->zeus_point[1];
 			vert[i].p[0] += m_state->zeus_point[2];
 		}
-		if (0)
-			vert[i].p[0] += m_state->zbase;
-		else {
+		//if (0)
+		//  //vert[i].p[0] += m_state->zbase;
+		//  vert[i].p[0] += reinterpret_cast<float&>(m_state->m_zeusbase[0x63]);
+		//else {
 			int shift;
 			shift = 1024 >> m_state->m_zeusbase[0x6c];
 			vert[i].p[0] += shift;
-		}
+		//  //float zScale = reinterpret_cast<float&>(m_state->m_zeusbase[0x63]);
+		//  //vert[i].p[0] += zScale;
+		//}
 
-		vert[i].p[2] += texdata >> 16;
-		vert[i].p[1] *= 256.0f;
-		vert[i].p[2] *= 256.0f;
+		vert[i].p[2] += (texdata >> 16) << 2;
+		vert[i].p[1] *= 256.0f / 4.0f;
+		vert[i].p[2] *= 256.0f / 4.0f;
 
 		// back face cull using polygon normal and first vertex
 		if (1 && i == 0)
@@ -1426,8 +1681,9 @@ void zeus2_renderer::zeus2_draw_quad(const uint32_t *databuffer, uint32_t texdat
 			unknown[0], unknown[1], unknown[2], unknown[3], unknown[4], unknown[5], unknown[6], unknown[7],
 			unknownFloat[0], unknownFloat[1], unknownFloat[2], unknownFloat[3]);
 	}
-	bool enable_perspective = true; // !(m_state->m_renderRegs[0x14] & 0x1);
+	bool enable_perspective = true; // !(m_state->m_renderRegs[0x14] & 0x2);
 	float clipVal = enable_perspective ? 1.0f / 512.0f / 4.0f : 0.0f;
+	//float clipVal = m_state->m_zbufmin / 4096.0f;
 	numverts = this->zclip_if_less(4, &vert[0], &clipvert[0], 4, clipVal);
 	if (numverts < 3)
 		return;
@@ -1436,7 +1692,7 @@ void zeus2_renderer::zeus2_draw_quad(const uint32_t *databuffer, uint32_t texdat
 	float yOrigin = reinterpret_cast<float&>(m_state->m_zeusbase[0x6b]);
 
 	float oozBase = (m_state->m_atlantis) ? 1024.0f : (m_state->m_thegrid) ? 512.0f : 512.0f;
-
+	//oozBase = 1 << m_state->m_zeusbase[0x6c];
 	maxx = maxy = -1000.0f;
 	for (i = 0; i < numverts; i++)
 	{
@@ -1445,13 +1701,13 @@ void zeus2_renderer::zeus2_draw_quad(const uint32_t *databuffer, uint32_t texdat
 		if (enable_perspective) {
 			// 412.0f here works for crusnexo
 			// 1024.0f works for mwskinsa
-			float ooz = oozBase / clipvert[i].p[0];
+			 float ooz = oozBase / clipvert[i].p[0];
 			//float ooz = 1024.0f / clipvert[i].p[0];
 			//float ooz = float(1 << m_state->m_zeusbase[0x6c]) / clipvert[i].p[0];
-
-			clipvert[i].x *= ooz;
-			clipvert[i].y *= ooz;
+			 clipvert[i].x *= ooz;
+			 clipvert[i].y *= ooz;
 		}
+
 		if (1) {
 			//clipvert[i].x += 256.5f / 1.0f;
 			//clipvert[i].y += 200.5f / 1.0f;
@@ -1482,7 +1738,7 @@ void zeus2_renderer::zeus2_draw_quad(const uint32_t *databuffer, uint32_t texdat
 	//extra.texwidth = 2 << ((texmode >> 2) & 7);
 	extra.texwidth = 0x20 << ((texmode >> 2) & 3);
 	//extra.texwidth = 0x2 << ((texmode >> 2) & 0xf);
-
+	//if (m_state->m_palSize == 16) extra.texwidth *= 2;
 	//switch (texmode)
 	//{
 	//case 0x14d:     // atlantis
@@ -1533,18 +1789,19 @@ void zeus2_renderer::zeus2_draw_quad(const uint32_t *databuffer, uint32_t texdat
 	//}
 
 	extra.solidcolor = 0;//m_zeusbase[0x00] & 0x7fff;
-	extra.zoffset = m_state->m_renderRegs[0x15] & 0xffff;
+	extra.zbufmin = m_state->m_zbufmin;
 	extra.alpha = 0;//m_zeusbase[0x4e];
-	extra.transcolor = 0x100; // !(texmode & 100) ? 0 : 0x100;
+	extra.transcolor = 0x100; // (texmode & 0x100) ? 0 : 0x100;
 	extra.texbase = WAVERAM_BLOCK0_EXT(m_state->zeus_texbase);
 	extra.palbase = m_state->waveram0_ptr_from_expanded_addr(m_state->m_zeusbase[0x41]);
 	//extra.depth_test_enable = !(m_state->m_renderRegs[0x40] & 0x020000);
 	// crusnexo text is R14=0x4062
 	extra.depth_test_enable = !(m_state->m_renderRegs[0x14] & 0x000020);
+	extra.depth_min_enable = false; // !(m_state->m_renderRegs[0x14] & 0x000040);
 	//extra.depth_test_enable = !(m_state->m_renderRegs[0x40] & 0x000002);
 	//extra.depth_test_enable = true; // (texmode & 0x0010);
 	extra.depth_write_enable = true;
-
+	extra.get_texel = (m_state->m_palSize==256) ? m_state->get_texel_8bit : m_state->get_texel_4bit;
 	// Note: Before being converted to the "poly.h" interface, this used to call the polylgcy function
 	//       poly_render_quad_fan.  The behavior seems to be the same as it once was after a few short
 	//       tests, but the (numverts == 5) statement below may actually be a quad fan instead of a 5-sided
@@ -1580,49 +1837,37 @@ void zeus2_renderer::render_poly_8bit(int32_t scanline, const extent_t& extent,
 	int x;
 
 	uint32_t addr = m_state->frame_addr_from_xy(0, scanline, true);
-	uint16_t *depthptr = &m_state->m_frameDepth[addr];
+	uint32_t *depthptr = &m_state->m_frameDepth[addr];
 	uint32_t *colorptr = &m_state->m_frameColor[addr];
 	for (x = extent.startx; x < extent.stopx; x++)
 	{
 		bool depth_pass = true;
 		if (object.depth_test_enable) {
-			//uint16_t *depthptr = WAVERAM_PTRDEPTH(m_state->zeus_renderbase, scanline, x);
-			int32_t depth = (curz >> 16) + object.zoffset;
-			//if (depth > 0x7fff) depth = 0x7fff;
-			if (depth > 0xffff) depth = 0xffff;
-			if (depth < 0 || depth > depthptr[x])
+			if (object.depth_min_enable && curz < object.zbufmin)
+				depth_pass = false;
+			if (curz < 0 || curz > depthptr[x])
 				depth_pass = false;
 			else if (object.depth_write_enable)
-				depthptr[x] = depth;
+				depthptr[x] = curz; // Should limit to 24 bits
 		}
 		if (depth_pass) {
 			int u0 = (curu >> 8);// & (texwidth - 1);
 			int v0 = (curv >> 8);// & 255;
 			int u1 = (u0 + 1);
 			int v1 = (v0 + 1);
-			uint8_t texel0 = m_state->get_texel_8bit(texbase, v0, u0, texwidth);
-			if (texel0 == object.transcolor)
+			uint8_t texel0 = object.get_texel(texbase, v0, u0, texwidth);
+			if (texel0 == transcolor)
 				continue;
-			uint8_t texel1 = m_state->get_texel_8bit(texbase, v0, u1, texwidth);
-			uint8_t texel2 = m_state->get_texel_8bit(texbase, v1, u0, texwidth);
-			uint8_t texel3 = m_state->get_texel_8bit(texbase, v1, u1, texwidth);
-			if (texel0 != transcolor)
+			uint8_t texel1 = object.get_texel(texbase, v0, u1, texwidth);
+			uint8_t texel2 = object.get_texel(texbase, v1, u0, texwidth);
+			uint8_t texel3 = object.get_texel(texbase, v1, u1, texwidth);
+			//if (texel0 != transcolor)
 			{
 				uint32_t color0 = m_state->m_pal_table[texel0];
 				uint32_t color1 = m_state->m_pal_table[texel1];
 				uint32_t color2 = m_state->m_pal_table[texel2];
 				uint32_t color3 = m_state->m_pal_table[texel3];
-				//uint32_t color0 = WAVERAM_READ16(palbase, texel0);
-				//uint32_t color1 = WAVERAM_READ16(palbase, texel1);
-				//uint32_t color2 = WAVERAM_READ16(palbase, texel2);
-				//uint32_t color3 = WAVERAM_READ16(palbase, texel3);
-				//color0 = ((color0 & 0x7c00) << 9) | ((color0 & 0x3e0) << 6) | ((color0 & 0x1f) << 3);
-				//color1 = ((color1 & 0x7c00) << 9) | ((color1 & 0x3e0) << 6) | ((color1 & 0x1f) << 3);
-				//color2 = ((color2 & 0x7c00) << 9) | ((color2 & 0x3e0) << 6) | ((color2 & 0x1f) << 3);
-				//color3 = ((color3 & 0x7c00) << 9) | ((color3 & 0x3e0) << 6) | ((color3 & 0x1f) << 3);
 				rgb_t filtered = rgbaint_t::bilinear_filter(color0, color1, color2, color3, curu, curv);
-				//WAVERAM_WRITEPIX(m_state->zeus_renderbase, scanline, x, filtered);
-				//*depthptr = depth;
 				colorptr[x] = filtered;
 			}
 		}
diff --git a/src/devices/video/zeus2.h b/src/devices/video/zeus2.h
index 4d40f2f..2e0bb9b 100644
--- a/src/devices/video/zeus2.h
+++ b/src/devices/video/zeus2.h
@@ -38,15 +38,17 @@ struct zeus2_poly_extra_data
 	const void *    palbase;
 	const void *    texbase;
 	uint16_t          solidcolor;
-	int16_t           zoffset;
+	int32_t           zbufmin;
 	uint16_t          transcolor;
 	uint16_t          texwidth;
 	uint16_t          color;
 	uint32_t          alpha;
 	uint32_t          ctrl_word;
 	bool            blend_enable;
+	bool            depth_min_enable;
 	bool            depth_test_enable;
 	bool            depth_write_enable;
+	uint8_t(*get_texel)(const void *, int, int, int);
 };
 
 /*************************************
@@ -128,6 +130,8 @@ public:
 
 	rectangle zeus_cliprect;
 
+	int m_palSize;
+	int m_zbufmin;
 	float zeus_matrix[3][3];
 	float zeus_point[3];
 	float zeus_point2[3];
@@ -135,12 +139,14 @@ public:
 	int zeus_quad_size;
 	uint32_t m_renderAddr;
 	bool m_thegrid;
-	uint32_t *m_directCmd;
 
 	uint32_t *waveram;
 	std::unique_ptr<uint32_t[]> m_frameColor;
-	std::unique_ptr<uint16_t[]> m_frameDepth;
+	std::unique_ptr<uint32_t[]> m_frameDepth;
 	uint32_t m_pal_table[0x100];
+	uint32_t m_ucode[0x200];
+	uint32_t m_curUCodeSrc;
+	uint32_t m_curPalTableSrc;
 
 	emu_timer *int_timer;
 	emu_timer *vblank_timer;
@@ -160,7 +166,8 @@ private:
 	void zeus2_register_update(offs_t offset, uint32_t oldval, int logit);
 	bool zeus2_fifo_process(const uint32_t *data, int numwords);
 	void zeus2_pointer_write(uint8_t which, uint32_t value, int logit);
-	void load_pal_table(void *wavePtr, uint32_t ctrl, int logit);
+	void load_pal_table(void *wavePtr, uint32_t ctrl, int type, int logit);
+	void load_ucode(void *wavePtr, uint32_t ctrl, int logit);
 	void zeus2_draw_model(uint32_t baseaddr, uint16_t count, int logit);
 	void log_fifo_command(const uint32_t *data, int numwords, const char *suffix);
 	void print_fifo_command(const uint32_t *data, int numwords, const char *suffix);
@@ -291,6 +298,11 @@ public:
 		return ((color & 0x7c00) << 9) | ((color & 0x3e0) << 6) | ((color & 0x1f) << 3);
 	}
 
+	inline uint32_t conv_rgb565_to_rgb32(uint16_t color)
+	{
+		return ((color & 0x7c00) << 9) | ((color & 0x3e0) << 6) | ((color & 0x8000) >> 5) | ((color & 0x1f) << 3);
+	}
+
 #ifdef UNUSED_FUNCTION
 	inline void WAVERAM_plot(int y, int x, uint32_t color)
 	{
@@ -339,19 +351,18 @@ public:
 	/*************************************
 	*  Inlines for texel accesses
 	*************************************/
-	inline uint8_t get_texel_8bit(const void *base, int y, int x, int width)
+	static inline uint8_t get_texel_8bit(const void *base, int y, int x, int width)
 	{
 		uint32_t byteoffs = (y / 2) * (width * 2) + ((x / 4) << 3) + ((y & 1) << 2) + (x & 3);
 		return WAVERAM_READ8(base, byteoffs);
 	}
 
-#ifdef UNUSED_FUNCTION
-	inline uint8_t get_texel_4bit(const void *base, int y, int x, int width)
+	static inline uint8_t get_texel_4bit(const void *base, int y, int x, int width)
 	{
 		uint32_t byteoffs = (y / 2) * (width * 2) + ((x / 8) << 3) + ((y & 1) << 2) + ((x / 2) & 3);
+		//uint32_t byteoffs = (y / 4) * (width * 4) + ((x / 4) << 3) + ((y & 3) << 1) + ((x / 2) & 1);
 		return (WAVERAM_READ8(base, byteoffs) >> (4 * (x & 1))) & 0x0f;
 	}
-#endif
 
 };
 
diff --git a/src/emu/addrmap.cpp b/src/emu/addrmap.cpp
index 24af3a1..31fabbe 100644
--- a/src/emu/addrmap.cpp
+++ b/src/emu/addrmap.cpp
@@ -401,11 +401,13 @@ address_map::~address_map()
 
 void address_map::configure(address_spacenum spacenum, u8 databits)
 {
-	assert(m_spacenum == spacenum);
+	if (spacenum != m_spacenum)
+		osd_printf_error("Space %d configured as address space %d\n", m_spacenum, spacenum);
+
 	if (m_databits == 0xff)
 		m_databits = databits;
-	else
-		assert(m_databits == databits);
+	else if (databits != m_databits)
+		osd_printf_error("Space %d configured with %d data bits when %d expected\n", m_spacenum, databits, m_databits);
 }
 
 
diff --git a/src/emu/bookkeeping.cpp b/src/emu/bookkeeping.cpp
index 3c1cb51..169d4d3 100644
--- a/src/emu/bookkeeping.cpp
+++ b/src/emu/bookkeeping.cpp
@@ -39,7 +39,7 @@ bookkeeping_manager::bookkeeping_manager(running_machine &machine)
 	machine.save().save_item(NAME(m_dispensed_tickets));
 
 	// register for configuration
-	machine.configuration().config_register("counters", config_saveload_delegate(&bookkeeping_manager::config_load, this), config_saveload_delegate(&bookkeeping_manager::config_save, this));
+	machine.configuration().config_register("counters", config_load_delegate(&bookkeeping_manager::config_load, this), config_save_delegate(&bookkeeping_manager::config_save, this));
 }
 
 
@@ -80,19 +80,19 @@ void bookkeeping_manager::increment_dispensed_tickets(int delta)
     and tickets
 -------------------------------------------------*/
 
-void bookkeeping_manager::config_load(config_type cfg_type, xml_data_node *parentnode)
+void bookkeeping_manager::config_load(config_type cfg_type, util::xml::data_node const *parentnode)
 {
-	xml_data_node const *coinnode, *ticketnode;
+	util::xml::data_node const *coinnode, *ticketnode;
 
 	/* on init, reset the counters */
-	if (cfg_type == config_type::CONFIG_TYPE_INIT)
+	if (cfg_type == config_type::INIT)
 	{
 		memset(m_coin_count, 0, sizeof(m_coin_count));
 		m_dispensed_tickets = 0;
 	}
 
 	/* only care about game-specific data */
-	if (cfg_type != config_type::CONFIG_TYPE_GAME)
+	if (cfg_type != config_type::GAME)
 		return;
 
 	/* might not have any data */
@@ -119,30 +119,32 @@ void bookkeeping_manager::config_load(config_type cfg_type, xml_data_node *paren
     and tickets
 -------------------------------------------------*/
 
-void bookkeeping_manager::config_save(config_type cfg_type, xml_data_node *parentnode)
+void bookkeeping_manager::config_save(config_type cfg_type, util::xml::data_node *parentnode)
 {
 	int i;
 
 	/* only care about game-specific data */
-	if (cfg_type != config_type::CONFIG_TYPE_GAME)
+	if (cfg_type != config_type::GAME)
 		return;
 
 	/* iterate over coin counters */
 	for (i = 0; i < COIN_COUNTERS; i++)
+	{
 		if (m_coin_count[i] != 0)
 		{
-			xml_data_node *coinnode = parentnode->add_child("coins", nullptr);
+			util::xml::data_node *coinnode = parentnode->add_child("coins", nullptr);
 			if (coinnode != nullptr)
 			{
 				coinnode->set_attribute_int("index", i);
 				coinnode->set_attribute_int("number", m_coin_count[i]);
 			}
 		}
+	}
 
 	/* output tickets */
 	if (m_dispensed_tickets != 0)
 	{
-		xml_data_node *tickets = parentnode->add_child("tickets", nullptr);
+		util::xml::data_node *tickets = parentnode->add_child("tickets", nullptr);
 		if (tickets != nullptr)
 			tickets->set_attribute_int("number", m_dispensed_tickets);
 	}
diff --git a/src/emu/bookkeeping.h b/src/emu/bookkeeping.h
index 131ae6e..e66fdf0 100644
--- a/src/emu/bookkeeping.h
+++ b/src/emu/bookkeeping.h
@@ -59,8 +59,8 @@ public:
 	// getters
 	running_machine &machine() const { return m_machine; }
 private:
-	void config_load(config_type cfg_type, xml_data_node *parentnode);
-	void config_save(config_type cfg_type, xml_data_node *parentnode);
+	void config_load(config_type cfg_type, util::xml::data_node const *parentnode);
+	void config_save(config_type cfg_type, util::xml::data_node *parentnode);
 
 	// internal state
 	running_machine &   m_machine;                  // reference to our machine
diff --git a/src/emu/config.cpp b/src/emu/config.cpp
index 8e3357a..fb1204f 100644
--- a/src/emu/config.cpp
+++ b/src/emu/config.cpp
@@ -36,7 +36,7 @@ configuration_manager::configuration_manager(running_machine &machine)
  *
  *************************************/
 
-void configuration_manager::config_register(const char* nodename, config_saveload_delegate load, config_saveload_delegate save)
+void configuration_manager::config_register(const char* nodename, config_load_delegate load, config_save_delegate save)
 {
 	config_element element;
 	element.name = nodename;
@@ -61,7 +61,7 @@ int configuration_manager::load_settings()
 
 	/* loop over all registrants and call their init function */
 	for (auto type : m_typelist)
-		type.load(config_type::CONFIG_TYPE_INIT, nullptr);
+		type.load(config_type::INIT, nullptr);
 
 	/* now load the controller file */
 	if (controller[0] != 0)
@@ -74,7 +74,7 @@ int configuration_manager::load_settings()
 			throw emu_fatalerror("Could not load controller file %s.cfg", controller);
 
 		/* load the XML */
-		if (!load_xml(file, config_type::CONFIG_TYPE_CONTROLLER))
+		if (!load_xml(file, config_type::CONTROLLER))
 			throw emu_fatalerror("Could not load controller file %s.cfg", controller);
 	}
 
@@ -82,16 +82,16 @@ int configuration_manager::load_settings()
 	emu_file file(machine().options().cfg_directory(), OPEN_FLAG_READ);
 	osd_file::error filerr = file.open("default.cfg");
 	if (filerr == osd_file::error::NONE)
-		load_xml(file, config_type::CONFIG_TYPE_DEFAULT);
+		load_xml(file, config_type::DEFAULT);
 
 	/* finally, load the game-specific file */
 	filerr = file.open(machine().basename(), ".cfg");
 	if (filerr == osd_file::error::NONE)
-		loaded = load_xml(file, config_type::CONFIG_TYPE_GAME);
+		loaded = load_xml(file, config_type::GAME);
 
 	/* loop over all registrants and call their final function */
 	for (auto type : m_typelist)
-		type.load(config_type::CONFIG_TYPE_FINAL, nullptr);
+		type.load(config_type::FINAL, nullptr);
 
 	/* if we didn't find a saved config, return 0 so the main core knows that it */
 	/* is the first time the game is run and it should diplay the disclaimer. */
@@ -103,22 +103,22 @@ void configuration_manager::save_settings()
 {
 	/* loop over all registrants and call their init function */
 	for (auto type : m_typelist)
-		type.save(config_type::CONFIG_TYPE_INIT, nullptr);
+		type.save(config_type::INIT, nullptr);
 
 	/* save the defaults file */
 	emu_file file(machine().options().cfg_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
 	osd_file::error filerr = file.open("default.cfg");
 	if (filerr == osd_file::error::NONE)
-		save_xml(file, config_type::CONFIG_TYPE_DEFAULT);
+		save_xml(file, config_type::DEFAULT);
 
 	/* finally, save the game-specific file */
 	filerr = file.open(machine().basename(), ".cfg");
 	if (filerr == osd_file::error::NONE)
-		save_xml(file, config_type::CONFIG_TYPE_GAME);
+		save_xml(file, config_type::GAME);
 
 	/* loop over all registrants and call their final function */
 	for (auto type : m_typelist)
-		type.save(config_type::CONFIG_TYPE_FINAL, nullptr);
+		type.save(config_type::FINAL, nullptr);
 }
 
 
@@ -131,27 +131,25 @@ void configuration_manager::save_settings()
 
 int configuration_manager::load_xml(emu_file &file, config_type which_type)
 {
-	xml_data_node *root, *confignode, *systemnode;
-	const char *srcfile;
-	int version, count;
-
 	/* read the file */
-	root = xml_data_node::file_read(file, nullptr);
+	std::unique_ptr<util::xml::data_node, void (*)(util::xml::data_node *)> const root(
+			util::xml::data_node::file_read(file, nullptr),
+			[] (util::xml::data_node *node) { node->file_free(); });
 	if (!root)
-		goto error;
+		return 0;
 
 	/* find the config node */
-	confignode = root->get_child("mameconfig");
+	util::xml::data_node const *const confignode = root->get_child("mameconfig");
 	if (!confignode)
-		goto error;
+		return 0;
 
 	/* validate the config data version */
-	version = confignode->get_attribute_int("version", 0);
+	int const version = confignode->get_attribute_int("version", 0);
 	if (version != CONFIG_VERSION)
-		goto error;
+		return 0;
 
 	/* strip off all the path crap from the source filename */
-	srcfile = strrchr(machine().system().source_file, '/');
+	const char *srcfile = strrchr(machine().system().source_file, '/');
 	if (!srcfile)
 		srcfile = strrchr(machine().system().source_file, '\\');
 	if (!srcfile)
@@ -162,8 +160,8 @@ int configuration_manager::load_xml(emu_file &file, config_type which_type)
 		srcfile++;
 
 	/* loop over all system nodes in the file */
-	count = 0;
-	for (systemnode = confignode->get_child("system"); systemnode; systemnode = systemnode->get_next_sibling("system"))
+	int count = 0;
+	for (util::xml::data_node const *systemnode = confignode->get_child("system"); systemnode; systemnode = systemnode->get_next_sibling("system"))
 	{
 		/* look up the name of the system here; skip if none */
 		const char *name = systemnode->get_attribute_string("name", "");
@@ -171,19 +169,19 @@ int configuration_manager::load_xml(emu_file &file, config_type which_type)
 		/* based on the file type, determine whether we have a match */
 		switch (which_type)
 		{
-			case config_type::CONFIG_TYPE_GAME:
-				/* only match on the specific game name */
-				if (strcmp(name, machine().system().name) != 0)
-					continue;
-				break;
-
-			case config_type::CONFIG_TYPE_DEFAULT:
-				/* only match on default */
-				if (strcmp(name, "default") != 0)
-					continue;
-				break;
-
-			case config_type::CONFIG_TYPE_CONTROLLER:
+		case config_type::GAME:
+			/* only match on the specific game name */
+			if (strcmp(name, machine().system().name) != 0)
+				continue;
+			break;
+
+		case config_type::DEFAULT:
+			/* only match on default */
+			if (strcmp(name, "default") != 0)
+				continue;
+			break;
+
+		case config_type::CONTROLLER:
 			{
 				int clone_of;
 				/* match on: default, game name, source file name, parent name, grandparent name */
@@ -195,8 +193,9 @@ int configuration_manager::load_xml(emu_file &file, config_type which_type)
 					continue;
 				break;
 			}
-			default:
-				break;
+
+		default:
+			break;
 		}
 
 		/* log that we are processing this entry */
@@ -211,16 +210,9 @@ int configuration_manager::load_xml(emu_file &file, config_type which_type)
 
 	/* error if this isn't a valid game match */
 	if (count == 0)
-		goto error;
+		return 0;
 
-	/* free the parser */
-	root->file_free();
 	return 1;
-
-error:
-	if (root)
-		root->file_free();
-	return 0;
 }
 
 
@@ -233,32 +225,33 @@ error:
 
 int configuration_manager::save_xml(emu_file &file, config_type which_type)
 {
-	xml_data_node *const root = xml_data_node::file_create();
-	xml_data_node *confignode, *systemnode;
+	std::unique_ptr<util::xml::data_node, void (*)(util::xml::data_node *)> const root(
+			util::xml::data_node::file_create(),
+			[] (util::xml::data_node *node) { node->file_free(); });
 
 	/* if we don't have a root, bail */
 	if (!root)
 		return 0;
 
 	/* create a config node */
-	confignode = root->add_child("mameconfig", nullptr);
+	util::xml::data_node *const confignode = root->add_child("mameconfig", nullptr);
 	if (!confignode)
-		goto error;
+		return 0;
 	confignode->set_attribute_int("version", CONFIG_VERSION);
 
 	/* create a system node */
-	systemnode = confignode->add_child("system", nullptr);
+	util::xml::data_node *const systemnode = confignode->add_child("system", nullptr);
 	if (!systemnode)
-		goto error;
-	systemnode->set_attribute("name", (which_type == config_type::CONFIG_TYPE_DEFAULT) ? "default" : machine().system().name);
+		return 0;
+	systemnode->set_attribute("name", (which_type == config_type::DEFAULT) ? "default" : machine().system().name);
 
 	/* create the input node and write it out */
 	/* loop over all registrants and call their save function */
 	for (auto type : m_typelist)
 	{
-		xml_data_node *curnode = systemnode->add_child(type.name.c_str(), nullptr);
+		util::xml::data_node *const curnode = systemnode->add_child(type.name.c_str(), nullptr);
 		if (!curnode)
-			goto error;
+			return 0;
 		type.save(which_type, curnode);
 
 		/* if nothing was added, just nuke the node */
@@ -270,10 +263,5 @@ int configuration_manager::save_xml(emu_file &file, config_type which_type)
 	root->file_write(file);
 
 	/* free and get out of here */
-	root->file_free();
 	return 1;
-
-error:
-	root->file_free();
-	return 0;
 }
diff --git a/src/emu/config.h b/src/emu/config.h
index 172f9f1..e9f528a 100644
--- a/src/emu/config.h
+++ b/src/emu/config.h
@@ -7,10 +7,10 @@
     Wrappers for handling MAME configuration files
 ***************************************************************************/
 
-#pragma once
+#ifndef MAME_EMU_CONFIG_H
+#define MAME_EMU_CONFIG_H
 
-#ifndef __CONFIG_H__
-#define __CONFIG_H__
+#pragma once
 
 #include "xmlfile.h"
 
@@ -24,11 +24,11 @@
 
 enum class config_type
 {
-	CONFIG_TYPE_INIT = 0,                   /* opportunity to initialize things first */
-	CONFIG_TYPE_CONTROLLER,                 /* loading from controller file */
-	CONFIG_TYPE_DEFAULT,                    /* loading from default.cfg */
-	CONFIG_TYPE_GAME,                   /* loading from game.cfg */
-	CONFIG_TYPE_FINAL                   /* opportunity to finish initialization */
+	INIT = 0,       // opportunity to initialize things first
+	CONTROLLER,     // loading from controller file
+	DEFAULT,        // loading from default.cfg
+	GAME,           // loading from game.cfg
+	FINAL           // opportunity to finish initialization
 };
 
 /*************************************
@@ -37,7 +37,8 @@ enum class config_type
  *
  *************************************/
 
-typedef delegate<void (config_type, xml_data_node *)> config_saveload_delegate;
+typedef delegate<void (config_type, util::xml::data_node const *)> config_load_delegate;
+typedef delegate<void (config_type, util::xml::data_node *)> config_save_delegate;
 
 // ======================> configuration_manager
 
@@ -45,16 +46,16 @@ class configuration_manager
 {
 	struct config_element
 	{
-		std::string              name;              /* node name */
-		config_saveload_delegate load;              /* load callback */
-		config_saveload_delegate save;              /* save callback */
+		std::string          name;              // node name
+		config_load_delegate load;              // load callback
+		config_save_delegate save;              // save callback
 	};
 
 public:
 	// construction/destruction
 	configuration_manager(running_machine &machine);
 
-	void config_register(const char* nodename, config_saveload_delegate load, config_saveload_delegate save);
+	void config_register(const char* nodename, config_load_delegate load, config_save_delegate save);
 	int load_settings();
 	void save_settings();
 
@@ -69,4 +70,4 @@ private:
 	std::vector<config_element> m_typelist;
 };
 
-#endif  /* __CONFIG_H__ */
+#endif  /* MAME_EMU_CONFIG_H */
diff --git a/src/emu/crsshair.cpp b/src/emu/crsshair.cpp
index 26d671e..f4e69d2 100644
--- a/src/emu/crsshair.cpp
+++ b/src/emu/crsshair.cpp
@@ -311,7 +311,7 @@ crosshair_manager::crosshair_manager(running_machine &machine)
 
 	/* register callbacks for when we load/save configurations */
 	if (m_usage)
-		machine.configuration().config_register("crosshairs", config_saveload_delegate(&crosshair_manager::config_load, this), config_saveload_delegate(&crosshair_manager::config_save, this));
+		machine.configuration().config_register("crosshairs", config_load_delegate(&crosshair_manager::config_load, this), config_save_delegate(&crosshair_manager::config_save, this));
 
 	/* register the animation callback */
 	if (machine.first_screen() != nullptr)
@@ -381,15 +381,12 @@ void crosshair_manager::render(screen_device &screen)
     configuration file
 -------------------------------------------------*/
 
-void crosshair_manager::config_load(config_type cfg_type, xml_data_node *parentnode)
+void crosshair_manager::config_load(config_type cfg_type, util::xml::data_node const *parentnode)
 {
 	/* Note: crosshair_load() is only registered if croshairs are used */
 
-	xml_data_node const *crosshairnode;
-	int auto_time;
-
 	/* we only care about game files */
-	if (cfg_type != config_type::CONFIG_TYPE_GAME)
+	if (cfg_type != config_type::GAME)
 		return;
 
 	/* might not have any data */
@@ -397,11 +394,9 @@ void crosshair_manager::config_load(config_type cfg_type, xml_data_node *parentn
 		return;
 
 	/* loop and get player crosshair info */
-	for (crosshairnode = parentnode->get_child("crosshair"); crosshairnode; crosshairnode = crosshairnode->get_next_sibling("crosshair"))
+	for (util::xml::data_node const *crosshairnode = parentnode->get_child("crosshair"); crosshairnode; crosshairnode = crosshairnode->get_next_sibling("crosshair"))
 	{
-		int  player, mode;
-
-		player = crosshairnode->get_attribute_int("player", -1);
+		int const player = crosshairnode->get_attribute_int("player", -1);
 
 		// check to make sure we have a valid player
 		if (player >= 0 && player < MAX_PLAYERS)
@@ -411,7 +406,7 @@ void crosshair_manager::config_load(config_type cfg_type, xml_data_node *parentn
 			if (crosshair.is_used())
 			{
 				// get, check, and store visibility mode
-				mode = crosshairnode->get_attribute_int("mode", CROSSHAIR_VISIBILITY_DEFAULT);
+				int const mode = crosshairnode->get_attribute_int("mode", CROSSHAIR_VISIBILITY_DEFAULT);
 				if (mode >= CROSSHAIR_VISIBILITY_OFF && mode <= CROSSHAIR_VISIBILITY_AUTO)
 				{
 					crosshair.set_mode(u8(mode));
@@ -427,10 +422,10 @@ void crosshair_manager::config_load(config_type cfg_type, xml_data_node *parentn
 	}
 
 	/* get, check, and store auto visibility time */
-	crosshairnode = parentnode->get_child("autotime");
-	if (crosshairnode != nullptr)
+	util::xml::data_node const *crosshairnode = parentnode->get_child("autotime");
+	if (crosshairnode)
 	{
-		auto_time = crosshairnode->get_attribute_int("val", CROSSHAIR_VISIBILITY_AUTOTIME_DEFAULT);
+		int const auto_time = crosshairnode->get_attribute_int("val", CROSSHAIR_VISIBILITY_AUTOTIME_DEFAULT);
 		if ((auto_time >= CROSSHAIR_VISIBILITY_AUTOTIME_MIN) && (auto_time <= CROSSHAIR_VISIBILITY_AUTOTIME_MAX))
 			m_auto_time = u8(auto_time);
 	}
@@ -442,25 +437,22 @@ void crosshair_manager::config_load(config_type cfg_type, xml_data_node *parentn
     configuration file
 -------------------------------------------------*/
 
-void crosshair_manager::config_save(config_type cfg_type, xml_data_node *parentnode)
+void crosshair_manager::config_save(config_type cfg_type, util::xml::data_node *parentnode)
 {
 	/* Note: crosshair_save() is only registered if crosshairs are used */
 
-	xml_data_node *crosshairnode;
-	int player;
-
 	/* we only care about game files */
-	if (cfg_type != config_type::CONFIG_TYPE_GAME)
+	if (cfg_type != config_type::GAME)
 		return;
 
-	for (player = 0; player < MAX_PLAYERS; player++)
+	for (int player = 0; player < MAX_PLAYERS; player++)
 	{
 		const render_crosshair &crosshair = *m_crosshair[player];
 
 		if (crosshair.is_used())
 		{
 			/* create a node */
-			crosshairnode = parentnode->add_child("crosshair", nullptr);
+			util::xml::data_node *const crosshairnode = parentnode->add_child("crosshair", nullptr);
 
 			if (crosshairnode != nullptr)
 			{
@@ -492,7 +484,7 @@ void crosshair_manager::config_save(config_type cfg_type, xml_data_node *parentn
 	if (m_auto_time != CROSSHAIR_VISIBILITY_AUTOTIME_DEFAULT)
 	{
 		/* create a node */
-		crosshairnode = parentnode->add_child("autotime", nullptr);
+		util::xml::data_node *const crosshairnode = parentnode->add_child("autotime", nullptr);
 
 		if (crosshairnode != nullptr)
 			crosshairnode->set_attribute_int("val", m_auto_time);
diff --git a/src/emu/crsshair.h b/src/emu/crsshair.h
index 7981c24..c733f0a 100644
--- a/src/emu/crsshair.h
+++ b/src/emu/crsshair.h
@@ -116,8 +116,8 @@ private:
 	void exit();
 	void animate(screen_device &device, bool vblank_state);
 
-	void config_load(config_type cfg_type, xml_data_node *parentnode);
-	void config_save(config_type cfg_type, xml_data_node *parentnode);
+	void config_load(config_type cfg_type, util::xml::data_node const *parentnode);
+	void config_save(config_type cfg_type, util::xml::data_node *parentnode);
 
 	// internal state
 	running_machine &   m_machine;                  // reference to our machine
diff --git a/src/emu/debug/debugcmd.cpp b/src/emu/debug/debugcmd.cpp
index e2f175f..5469670 100644
--- a/src/emu/debug/debugcmd.cpp
+++ b/src/emu/debug/debugcmd.cpp
@@ -179,6 +179,8 @@ debugger_commands::debugger_commands(running_machine& machine, debugger_cpu& cpu
 	m_console.register_command("wpd",       CMDFLAG_NONE, AS_DATA, 3, 5, std::bind(&debugger_commands::execute_wpset, this, _1, _2, _3));
 	m_console.register_command("wpiset",    CMDFLAG_NONE, AS_IO, 3, 5, std::bind(&debugger_commands::execute_wpset, this, _1, _2, _3));
 	m_console.register_command("wpi",       CMDFLAG_NONE, AS_IO, 3, 5, std::bind(&debugger_commands::execute_wpset, this, _1, _2, _3));
+	m_console.register_command("wposet",    CMDFLAG_NONE, AS_DECRYPTED_OPCODES, 3, 5, std::bind(&debugger_commands::execute_wpset, this, _1, _2, _3));
+	m_console.register_command("wpo",       CMDFLAG_NONE, AS_DECRYPTED_OPCODES, 3, 5, std::bind(&debugger_commands::execute_wpset, this, _1, _2, _3));
 	m_console.register_command("wpclear",   CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_wpclear, this, _1, _2, _3));
 	m_console.register_command("wpdisable", CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_wpdisenable, this, _1, _2, _3));
 	m_console.register_command("wpenable",  CMDFLAG_NONE, 1, 0, 1, std::bind(&debugger_commands::execute_wpdisenable, this, _1, _2, _3));
@@ -201,14 +203,17 @@ debugger_commands::debugger_commands(running_machine& machine, debugger_cpu& cpu
 	m_console.register_command("save",      CMDFLAG_NONE, AS_PROGRAM, 3, 4, std::bind(&debugger_commands::execute_save, this, _1, _2, _3));
 	m_console.register_command("saved",     CMDFLAG_NONE, AS_DATA, 3, 4, std::bind(&debugger_commands::execute_save, this, _1, _2, _3));
 	m_console.register_command("savei",     CMDFLAG_NONE, AS_IO, 3, 4, std::bind(&debugger_commands::execute_save, this, _1, _2, _3));
+	m_console.register_command("saveo",     CMDFLAG_NONE, AS_DECRYPTED_OPCODES, 3, 4, std::bind(&debugger_commands::execute_save, this, _1, _2, _3));
 
 	m_console.register_command("load",      CMDFLAG_NONE, AS_PROGRAM, 3, 4, std::bind(&debugger_commands::execute_load, this, _1, _2, _3));
 	m_console.register_command("loadd",     CMDFLAG_NONE, AS_DATA, 3, 4, std::bind(&debugger_commands::execute_load, this, _1, _2, _3));
 	m_console.register_command("loadi",     CMDFLAG_NONE, AS_IO, 3, 4, std::bind(&debugger_commands::execute_load, this, _1, _2, _3));
+	m_console.register_command("loado",     CMDFLAG_NONE, AS_DECRYPTED_OPCODES, 3, 4, std::bind(&debugger_commands::execute_load, this, _1, _2, _3));
 
 	m_console.register_command("dump",      CMDFLAG_NONE, AS_PROGRAM, 3, 7, std::bind(&debugger_commands::execute_dump, this, _1, _2, _3));
 	m_console.register_command("dumpd",     CMDFLAG_NONE, AS_DATA, 3, 7, std::bind(&debugger_commands::execute_dump, this, _1, _2, _3));
 	m_console.register_command("dumpi",     CMDFLAG_NONE, AS_IO, 3, 7, std::bind(&debugger_commands::execute_dump, this, _1, _2, _3));
+	m_console.register_command("dumpo",     CMDFLAG_NONE, AS_DECRYPTED_OPCODES, 3, 7, std::bind(&debugger_commands::execute_dump, this, _1, _2, _3));
 
 	m_console.register_command("cheatinit", CMDFLAG_NONE, 0, 0, 4, std::bind(&debugger_commands::execute_cheatinit, this, _1, _2, _3));
 	m_console.register_command("ci",        CMDFLAG_NONE, 0, 0, 4, std::bind(&debugger_commands::execute_cheatinit, this, _1, _2, _3));
@@ -233,6 +238,8 @@ debugger_commands::debugger_commands(running_machine& machine, debugger_cpu& cpu
 	m_console.register_command("findd",     CMDFLAG_KEEP_QUOTES, AS_DATA, 3, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_find, this, _1, _2, _3));
 	m_console.register_command("fi",        CMDFLAG_KEEP_QUOTES, AS_IO, 3, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_find, this, _1, _2, _3));
 	m_console.register_command("findi",     CMDFLAG_KEEP_QUOTES, AS_IO, 3, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_find, this, _1, _2, _3));
+	m_console.register_command("fo",        CMDFLAG_KEEP_QUOTES, AS_DECRYPTED_OPCODES, 3, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_find, this, _1, _2, _3));
+	m_console.register_command("findo",     CMDFLAG_KEEP_QUOTES, AS_DECRYPTED_OPCODES, 3, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_find, this, _1, _2, _3));
 
 	m_console.register_command("dasm",      CMDFLAG_NONE, 0, 3, 5, std::bind(&debugger_commands::execute_dasm, this, _1, _2, _3));
 
@@ -247,6 +254,7 @@ debugger_commands::debugger_commands(running_machine& machine, debugger_cpu& cpu
 	m_console.register_command("pcatmemp",  CMDFLAG_NONE, AS_PROGRAM, 1, 2, std::bind(&debugger_commands::execute_pcatmem, this, _1, _2, _3));
 	m_console.register_command("pcatmemd",  CMDFLAG_NONE, AS_DATA,    1, 2, std::bind(&debugger_commands::execute_pcatmem, this, _1, _2, _3));
 	m_console.register_command("pcatmemi",  CMDFLAG_NONE, AS_IO,      1, 2, std::bind(&debugger_commands::execute_pcatmem, this, _1, _2, _3));
+	m_console.register_command("pcatmemo",  CMDFLAG_NONE, AS_DECRYPTED_OPCODES, 1, 2, std::bind(&debugger_commands::execute_pcatmem, this, _1, _2, _3));
 
 	m_console.register_command("snap",      CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_snap, this, _1, _2, _3));
 
@@ -255,6 +263,7 @@ debugger_commands::debugger_commands(running_machine& machine, debugger_cpu& cpu
 	m_console.register_command("map",       CMDFLAG_NONE, AS_PROGRAM, 1, 1, std::bind(&debugger_commands::execute_map, this, _1, _2, _3));
 	m_console.register_command("mapd",      CMDFLAG_NONE, AS_DATA, 1, 1, std::bind(&debugger_commands::execute_map, this, _1, _2, _3));
 	m_console.register_command("mapi",      CMDFLAG_NONE, AS_IO, 1, 1, std::bind(&debugger_commands::execute_map, this, _1, _2, _3));
+	m_console.register_command("mapo",      CMDFLAG_NONE, AS_DECRYPTED_OPCODES, 1, 1, std::bind(&debugger_commands::execute_map, this, _1, _2, _3));
 	m_console.register_command("memdump",   CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_memdump, this, _1, _2, _3));
 
 	m_console.register_command("symlist",   CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_symlist, this, _1, _2, _3));
@@ -2168,6 +2177,7 @@ void debugger_commands::execute_cheatlist(int ref, int params, const char *param
 		case AS_PROGRAM:    spaceletter = 'p';  break;
 		case AS_DATA:   spaceletter = 'd';  break;
 		case AS_IO:     spaceletter = 'i';  break;
+		case AS_DECRYPTED_OPCODES: spaceletter = 'o'; break;
 	}
 
 	switch (m_cheat.width)
diff --git a/src/emu/debug/debugcpu.cpp b/src/emu/debug/debugcpu.cpp
index 5bab1e3..98fa6c9 100644
--- a/src/emu/debug/debugcpu.cpp
+++ b/src/emu/debug/debugcpu.cpp
@@ -220,7 +220,7 @@ bool debugger_cpu::comment_save()
 	bool comments_saved = false;
 
 	// if we don't have a root, bail
-	xml_data_node *const root = xml_data_node::file_create();
+	util::xml::data_node *const root = util::xml::data_node::file_create();
 	if (root == nullptr)
 		return false;
 
@@ -228,13 +228,13 @@ bool debugger_cpu::comment_save()
 	try
 	{
 		// create a comment node
-		xml_data_node *const commentnode = root->add_child("mamecommentfile", nullptr);
+		util::xml::data_node *const commentnode = root->add_child("mamecommentfile", nullptr);
 		if (commentnode == nullptr)
 			throw emu_exception();
 		commentnode->set_attribute_int("version", COMMENT_VERSION);
 
 		// create a system node
-		xml_data_node *const systemnode = commentnode->add_child("system", nullptr);
+		util::xml::data_node *const systemnode = commentnode->add_child("system", nullptr);
 		if (systemnode == nullptr)
 			throw emu_exception();
 		systemnode->set_attribute("name", m_machine.system().name);
@@ -245,7 +245,7 @@ bool debugger_cpu::comment_save()
 			if (device.debug() && device.debug()->comment_count() > 0)
 			{
 				// create a node for this device
-				xml_data_node *const curnode = systemnode->add_child("cpu", nullptr);
+				util::xml::data_node *const curnode = systemnode->add_child("cpu", nullptr);
 				if (curnode == nullptr)
 					throw emu_exception();
 				curnode->set_attribute("tag", device.tag());
@@ -295,7 +295,7 @@ bool debugger_cpu::comment_load(bool is_inline)
 		return false;
 
 	// wrap in a try/catch to handle errors
-	xml_data_node *const root = xml_data_node::file_read(file, nullptr);
+	util::xml::data_node *const root = util::xml::data_node::file_read(file, nullptr);
 	try
 	{
 		// read the file
@@ -303,7 +303,7 @@ bool debugger_cpu::comment_load(bool is_inline)
 			throw emu_exception();
 
 		// find the config node
-		xml_data_node const *const commentnode = root->get_child("mamecommentfile");
+		util::xml::data_node const *const commentnode = root->get_child("mamecommentfile");
 		if (commentnode == nullptr)
 			throw emu_exception();
 
@@ -313,13 +313,13 @@ bool debugger_cpu::comment_load(bool is_inline)
 			throw emu_exception();
 
 		// check to make sure the file is applicable
-		xml_data_node const *const systemnode = commentnode->get_child("system");
+		util::xml::data_node const *const systemnode = commentnode->get_child("system");
 		const char *const name = systemnode->get_attribute_string("name", "");
 		if (strcmp(name, m_machine.system().name) != 0)
 			throw emu_exception();
 
 		// iterate over devices
-		for (xml_data_node const *cpunode = systemnode->get_child("cpu"); cpunode; cpunode = cpunode->get_next_sibling("cpu"))
+		for (util::xml::data_node const *cpunode = systemnode->get_child("cpu"); cpunode; cpunode = cpunode->get_next_sibling("cpu"))
 		{
 			const char *cputag_name = cpunode->get_attribute_string("tag", "");
 			device_t *device = m_machine.device(cputag_name);
@@ -369,16 +369,11 @@ u8 debugger_cpu::read_byte(address_space &space, offs_t address, bool apply_tran
 	space.set_debugger_access(true);
 
 	/* translate if necessary; if not mapped, return 0xff */
-	u64 custom;
 	u8 result;
 	if (apply_translation && !memory.translate(space.spacenum(), TRANSLATE_READ_DEBUG, address))
 	{
 		result = 0xff;
 	}
-	else if (memory.read(space.spacenum(), address, 1, custom))
-	{   /* if there is a custom read handler, and it returns true, use that value */
-		result = custom;
-	}
 	else
 	{   /* otherwise, call the byte reading function for the translated address */
 		result = space.read_byte(address);
@@ -422,15 +417,10 @@ u16 debugger_cpu::read_word(address_space &space, offs_t address, bool apply_tra
 		space.set_debugger_access(true);
 
 		/* translate if necessary; if not mapped, return 0xffff */
-		u64 custom;
 		if (apply_translation && !memory.translate(space.spacenum(), TRANSLATE_READ_DEBUG, address))
 		{
 			result = 0xffff;
 		}
-		else if (memory.read(space.spacenum(), address, 2, custom))
-		{   /* if there is a custom read handler, and it returns true, use that value */
-			result = custom;
-		}
 		else
 		{   /* otherwise, call the byte reading function for the translated address */
 			result = space.read_word(address);
@@ -475,15 +465,10 @@ u32 debugger_cpu::read_dword(address_space &space, offs_t address, bool apply_tr
 		m_debugger_access = true;
 		space.set_debugger_access(true);
 
-		u64 custom;
 		if (apply_translation && !memory.translate(space.spacenum(), TRANSLATE_READ_DEBUG, address))
 		{   /* translate if necessary; if not mapped, return 0xffffffff */
 			result = 0xffffffff;
 		}
-		else if (memory.read(space.spacenum(), address, 4, custom))
-		{   /* if there is a custom read handler, and it returns true, use that value */
-			result = custom;
-		}
 		else
 		{   /* otherwise, call the byte reading function for the translated address */
 			result = space.read_dword(address);
@@ -529,15 +514,10 @@ u64 debugger_cpu::read_qword(address_space &space, offs_t address, bool apply_tr
 		space.set_debugger_access(true);
 
 		/* translate if necessary; if not mapped, return 0xffffffffffffffff */
-		u64 custom;
 		if (apply_translation && !memory.translate(space.spacenum(), TRANSLATE_READ_DEBUG, address))
 		{
 			result = ~u64(0);
 		}
-		else if (memory.read(space.spacenum(), address, 8, custom))
-		{   /* if there is a custom read handler, and it returns true, use that value */
-			result = custom;
-		}
 		else
 		{   /* otherwise, call the byte reading function for the translated address */
 			result = space.read_qword(address);
@@ -591,10 +571,6 @@ void debugger_cpu::write_byte(address_space &space, offs_t address, u8 data, boo
 	if (apply_translation && !memory.translate(space.spacenum(), TRANSLATE_WRITE_DEBUG, address))
 		;
 
-	/* if there is a custom write handler, and it returns true, use that */
-	else if (memory.write(space.spacenum(), address, 1, data))
-		;
-
 	/* otherwise, call the byte reading function for the translated address */
 	else
 		space.write_byte(address, data);
@@ -645,10 +621,6 @@ void debugger_cpu::write_word(address_space &space, offs_t address, u16 data, bo
 		if (apply_translation && !memory.translate(space.spacenum(), TRANSLATE_WRITE_DEBUG, address))
 			;
 
-		/* if there is a custom write handler, and it returns true, use that */
-		else if (memory.write(space.spacenum(), address, 2, data))
-			;
-
 		/* otherwise, call the byte reading function for the translated address */
 		else
 			space.write_word(address, data);
@@ -699,10 +671,6 @@ void debugger_cpu::write_dword(address_space &space, offs_t address, u32 data, b
 		if (apply_translation && !memory.translate(space.spacenum(), TRANSLATE_WRITE_DEBUG, address))
 			;
 
-		/* if there is a custom write handler, and it returns true, use that */
-		else if (memory.write(space.spacenum(), address, 4, data))
-			;
-
 		/* otherwise, call the byte reading function for the translated address */
 		else
 			space.write_dword(address, data);
@@ -754,10 +722,6 @@ void debugger_cpu::write_qword(address_space &space, offs_t address, u64 data, b
 		if (apply_translation && !memory.translate(space.spacenum(), TRANSLATE_WRITE_DEBUG, address))
 			;
 
-		/* if there is a custom write handler, and it returns true, use that */
-		else if (memory.write(space.spacenum(), address, 8, data))
-			;
-
 		/* otherwise, call the byte reading function for the translated address */
 		else
 			space.write_qword(address, data);
@@ -802,15 +766,8 @@ u64 debugger_cpu::read_opcode(address_space &space, offs_t address, int size)
 	/* keep in logical range */
 	address &= space.logbytemask();
 
-	/* return early if we got the result directly */
 	m_debugger_access = true;
 	space.set_debugger_access(true);
-	if (memory.readop(address, size, result2))
-	{
-		m_debugger_access = false;
-		space.set_debugger_access(false);
-		return result2;
-	}
 
 	/* if we're bigger than the address bus, break into smaller pieces */
 	if (size > space.data_width() / 8)
@@ -878,6 +835,7 @@ u64 debugger_cpu::read_opcode(address_space &space, offs_t address, int size)
 
 		/* dump opcodes in qwords from a qword-sized bus */
 		case 88:
+		case 86: // sharc case, 48-bits opcodes
 			break;
 
 		default:
@@ -925,6 +883,7 @@ u64 debugger_cpu::read_opcode(address_space &space, offs_t address, int size)
 			break;
 
 		case 8:
+		case 6:
 			result = space.direct().read_qword(address & ~7, addrxor);
 			if (!QWORD_ALIGNED(address))
 			{
@@ -1703,6 +1662,8 @@ device_debug::device_debug(device_t &device)
 				m_symtable.add("logunmapd", (void *)&m_memory->space(AS_DATA), get_logunmap, set_logunmap);
 			if (m_memory->has_space(AS_IO))
 				m_symtable.add("logunmapi", (void *)&m_memory->space(AS_IO), get_logunmap, set_logunmap);
+			if (m_memory->has_space(AS_DECRYPTED_OPCODES))
+				m_symtable.add("logunmapo", (void *)&m_memory->space(AS_DECRYPTED_OPCODES), get_logunmap, set_logunmap);
 		}
 
 		// add all registers into it
@@ -2578,12 +2539,12 @@ const char *device_debug::comment_text(offs_t addr) const
 //  given XML data node
 //-------------------------------------------------
 
-bool device_debug::comment_export(xml_data_node &curnode)
+bool device_debug::comment_export(util::xml::data_node &curnode)
 {
 	// iterate through the comments
 	for (const auto & elem : m_comment_set)
 	{
-		xml_data_node *datanode = curnode.add_child("comment", xml_normalize_string(elem.m_text.c_str()));
+		util::xml::data_node *datanode = curnode.add_child("comment", util::xml::normalize_string(elem.m_text.c_str()));
 		if (datanode == nullptr)
 			return false;
 		datanode->set_attribute_int("address", elem.m_address);
@@ -2599,10 +2560,10 @@ bool device_debug::comment_export(xml_data_node &curnode)
 //  given XML data node
 //-------------------------------------------------
 
-bool device_debug::comment_import(xml_data_node const &cpunode, bool is_inline)
+bool device_debug::comment_import(util::xml::data_node const &cpunode, bool is_inline)
 {
 	// iterate through nodes
-	for (xml_data_node const *datanode = cpunode.get_child("comment"); datanode; datanode = datanode->get_next_sibling("comment"))
+	for (util::xml::data_node const *datanode = cpunode.get_child("comment"); datanode; datanode = datanode->get_next_sibling("comment"))
 	{
 		// extract attributes
 		offs_t address = datanode->get_attribute_int("address", 0);
@@ -3424,6 +3385,7 @@ void device_debug::tracer::update(offs_t pc)
 	// log this PC
 	m_nextdex = (m_nextdex + 1) % TRACE_LOOPS;
 	m_history[m_nextdex] = pc;
+	fflush(&m_file);
 }
 
 
@@ -3435,6 +3397,7 @@ void device_debug::tracer::vprintf(const char *format, va_list va)
 {
 	// pass through to the file
 	vfprintf(&m_file, format, va);
+	fflush(&m_file);
 }
 
 
diff --git a/src/emu/debug/debugcpu.h b/src/emu/debug/debugcpu.h
index 079b17d..c01cc0e 100644
--- a/src/emu/debug/debugcpu.h
+++ b/src/emu/debug/debugcpu.h
@@ -18,6 +18,9 @@
 #include <set>
 
 
+namespace util { namespace xml { class data_node; } }
+
+
 //**************************************************************************
 //  CONSTANTS
 //**************************************************************************
@@ -37,9 +40,6 @@ constexpr int COMMENT_VERSION       = 1;
 typedef int (*debug_instruction_hook_func)(device_t &device, offs_t curpc);
 
 
-class xml_data_node;
-
-
 // ======================> device_debug
 
 // [TODO] This whole thing is terrible.
@@ -242,8 +242,8 @@ public:
 	const char *comment_text(offs_t addr) const;
 	u32 comment_count() const { return m_comment_set.size(); }
 	u32 comment_change_count() const { return m_comment_change; }
-	bool comment_export(xml_data_node &node);
-	bool comment_import(xml_data_node const &node, bool is_inline);
+	bool comment_export(util::xml::data_node &node);
+	bool comment_import(util::xml::data_node const &node, bool is_inline);
 	u32 compute_opcode_crc32(offs_t pc) const;
 
 	// history
diff --git a/src/emu/devcb.cpp b/src/emu/devcb.cpp
index 3d851ee..12f84a0 100644
--- a/src/emu/devcb.cpp
+++ b/src/emu/devcb.cpp
@@ -22,11 +22,27 @@
 
 devcb_base::devcb_base(device_t &device, u64 defmask)
 	: m_device(device),
+		m_type(CALLBACK_NONE),
+		m_target_tag(nullptr),
+		m_target_int(0),
+		m_space_tag(nullptr),
+		m_space_num(AS_0),
+		m_space(nullptr),
 		m_rshift(0),
 		m_mask(defmask),
+		m_defmask(defmask),
 		m_xor(0)
 {
-	reset();
+	m_target.ptr = nullptr;
+}
+
+
+//-------------------------------------------------
+//  devcb_base - destructor
+//-------------------------------------------------
+
+devcb_base::~devcb_base()
+{
 }
 
 
@@ -45,6 +61,8 @@ void devcb_base::reset(callback_type type)
 	m_target.ptr = nullptr;
 	m_rshift = 0;
 	m_mask = ~u64(0);
+	m_xor = 0;
+	devcb_reset();
 }
 
 
@@ -59,6 +77,26 @@ void devcb_base::resolve_ioport()
 	m_target.ioport = (m_target_tag != nullptr) ? m_device.owner()->ioport(m_target_tag) : nullptr;
 	if (m_target.ioport == nullptr)
 		throw emu_fatalerror("Unable to resolve I/O port callback reference to '%s' in device '%s'\n", m_target_tag, m_device.tag());
+
+	// adjust the mask to match the port bits
+	u64 port_mask = 0;
+	for (const ioport_field &field : m_target.ioport->fields())
+		port_mask |= field.mask();
+	m_mask = shift_mask(port_mask);
+}
+
+
+//-------------------------------------------------
+//  resolve_membank - resolve a memory bank or
+//  fatal error if we can't find it
+//-------------------------------------------------
+
+void devcb_base::resolve_membank()
+{
+	// attempt to resolve, fatal error if fail
+	m_target.membank = (m_target_tag != nullptr) ? m_device.owner()->membank(m_target_tag) : nullptr;
+	if (m_target.membank == nullptr)
+		throw emu_fatalerror("Unable to resolve memory bank callback reference to '%s' in device '%s'\n", m_target_tag, m_device.tag());
 }
 
 
@@ -109,27 +147,37 @@ void devcb_base::resolve_space()
 
 devcb_read_base::devcb_read_base(device_t &device, u64 defmask)
 	: devcb_base(device, defmask),
-		m_adapter(nullptr)
+		m_adapter(&devcb_read_base::read_unresolved_adapter)
 {
 }
 
 
 //-------------------------------------------------
-//  reset - reset/initialize state
+//  devcb_reset - reset/initialize local state
 //-------------------------------------------------
 
-void devcb_read_base::reset(callback_type type)
+void devcb_read_base::devcb_reset()
 {
-	// parent first
-	devcb_base::reset(type);
-
-	// local stuff
 	m_readline = read_line_delegate();
 	m_read8 = read8_delegate();
 	m_read16 = read16_delegate();
 	m_read32 = read32_delegate();
 	m_read64 = read64_delegate();
 	m_adapter = &devcb_read_base::read_unresolved_adapter;
+	m_chain = nullptr;
+}
+
+
+//-------------------------------------------------
+//  chain_alloc - add another callback to the
+//  input chain
+//-------------------------------------------------
+
+devcb_read_base &devcb_read_base::chain_alloc()
+{
+	// set up the chained callback pointer
+	m_chain.reset(new devcb_read_base(m_device, m_defmask));
+	return *m_chain;
 }
 
 
@@ -160,6 +208,7 @@ void devcb_read_base::resolve()
 				m_readline.bind_relative_to(*m_device.owner());
 				m_target_int = 0;
 				m_adapter = m_readline.isnull() ? &devcb_read_base::read_constant_adapter : &devcb_read_base::read_line_adapter;
+				m_mask = shift_mask(1);
 				break;
 
 			case CALLBACK_8:
@@ -167,6 +216,7 @@ void devcb_read_base::resolve()
 				m_read8.bind_relative_to(*m_device.owner());
 				m_target_int = 0;
 				m_adapter = m_read8.isnull() ? &devcb_read_base::read_constant_adapter : &devcb_read_base::read8_adapter;
+				m_mask = shift_mask(0xff);
 				break;
 
 			case CALLBACK_16:
@@ -174,6 +224,7 @@ void devcb_read_base::resolve()
 				m_read16.bind_relative_to(*m_device.owner());
 				m_target_int = 0;
 				m_adapter = m_read16.isnull() ? &devcb_read_base::read_constant_adapter : &devcb_read_base::read16_adapter;
+				m_mask = shift_mask(0xffff);
 				break;
 
 			case CALLBACK_32:
@@ -181,6 +232,7 @@ void devcb_read_base::resolve()
 				m_read32.bind_relative_to(*m_device.owner());
 				m_target_int = 0;
 				m_adapter = m_read32.isnull() ? &devcb_read_base::read_constant_adapter : &devcb_read_base::read32_adapter;
+				m_mask = shift_mask(0xffffffff);
 				break;
 
 			case CALLBACK_64:
@@ -191,20 +243,30 @@ void devcb_read_base::resolve()
 				break;
 
 			case CALLBACK_IOPORT:
+				name = m_target_tag;
 				resolve_ioport();
 				m_target_int = 0;
-				m_adapter = (m_target.ioport == nullptr) ? &devcb_read_base::read_constant_adapter : &devcb_read_base::read_ioport_adapter;
+				m_adapter = &devcb_read_base::read_ioport_adapter;
 				break;
 
+			case CALLBACK_MEMBANK:
+				throw emu_fatalerror("Device read callbacks can't be connected to bank switches\n");
+
 			case CALLBACK_LOG:
 				m_adapter = &devcb_read_base::read_logged_adapter;
+				m_mask = 0;
 				break;
 
 			case CALLBACK_CONSTANT:
+				if (m_xor != 0)
+					throw emu_fatalerror("devcb_read: Attempt to invert constant value (%lX ^ %lX)\n", (unsigned long)shift_mask(m_target_int), (unsigned long)m_xor);
 				m_adapter = &devcb_read_base::read_constant_adapter;
+				m_mask = shift_mask(m_target_int);
 				break;
 
 			case CALLBACK_INPUTLINE:
+			case CALLBACK_ASSERTLINE:
+			case CALLBACK_CLEARLINE:
 				throw emu_fatalerror("Device read callbacks can't be connected to input lines\n");
 		}
 	}
@@ -212,6 +274,15 @@ void devcb_read_base::resolve()
 	{
 		throw emu_fatalerror("devcb_read: Error performing a late bind of type %s to %s (name=%s)\n", binderr.m_actual_type.name(), binderr.m_target_type.name(), name);
 	}
+
+	// resolve callback chain recursively
+	if (m_chain != nullptr)
+		m_chain->resolve();
+
+	// protect against bus contention (the masks must not overlap)
+	for (const devcb_read_base *chained_cb = m_chain.get(); chained_cb != nullptr; chained_cb = chained_cb->m_chain.get())
+		if ((m_mask & chained_cb->m_mask) != 0)
+			throw emu_fatalerror("Device %s read callback (name=%s) overlaps with chained callback (%lX & %lX)", m_device.tag(), name, (unsigned long)m_mask, (unsigned long)chained_cb->m_mask);
 }
 
 
@@ -305,14 +376,14 @@ u64 devcb_read_base::read_ioport_adapter(address_space &space, offs_t offset, u6
 
 
 //-------------------------------------------------
-//  read_logged_adapter - log a read and return a
-//  constant
+//  read_logged_adapter - log a read and return
+//  zero
 //-------------------------------------------------
 
 u64 devcb_read_base::read_logged_adapter(address_space &space, offs_t offset, u64 mask)
 {
-	m_device.logerror("%s: read %s\n", m_device.machine().describe_context(), m_target_tag);
-	return shift_mask_xor(m_target_int);
+	m_device.logerror("%s: %s\n", m_device.machine().describe_context(), m_target_tag);
+	return 0;
 }
 
 
@@ -322,7 +393,7 @@ u64 devcb_read_base::read_logged_adapter(address_space &space, offs_t offset, u6
 
 u64 devcb_read_base::read_constant_adapter(address_space &space, offs_t offset, u64 mask)
 {
-	return shift_mask_xor(m_target_int);
+	return shift_mask(m_target_int);
 }
 
 
@@ -337,27 +408,37 @@ u64 devcb_read_base::read_constant_adapter(address_space &space, offs_t offset,
 
 devcb_write_base::devcb_write_base(device_t &device, u64 defmask)
 	: devcb_base(device, defmask),
-		m_adapter(nullptr)
+		m_adapter(&devcb_write_base::write_unresolved_adapter)
 {
 }
 
 
 //-------------------------------------------------
-//  reset - reset/initialize state
+//  devcb_reset - reset/initialize local state
 //-------------------------------------------------
 
-void devcb_write_base::reset(callback_type type)
+void devcb_write_base::devcb_reset()
 {
-	// parent first
-	devcb_base::reset(type);
-
-	// local stuff
 	m_writeline = write_line_delegate();
 	m_write8 = write8_delegate();
 	m_write16 = write16_delegate();
 	m_write32 = write32_delegate();
 	m_write64 = write64_delegate();
 	m_adapter = &devcb_write_base::write_unresolved_adapter;
+	m_chain = nullptr;
+}
+
+
+//-------------------------------------------------
+//  chain_alloc - add another callback to the
+//  output chain
+//-------------------------------------------------
+
+devcb_write_base &devcb_write_base::chain_alloc()
+{
+	// set up the chained callback pointer
+	m_chain.reset(new devcb_write_base(m_device, m_defmask));
+	return *m_chain;
 }
 
 
@@ -418,6 +499,11 @@ void devcb_write_base::resolve()
 				m_adapter = (m_target.ioport == nullptr) ? &devcb_write_base::write_noop_adapter : &devcb_write_base::write_ioport_adapter;
 				break;
 
+			case CALLBACK_MEMBANK:
+				resolve_membank();
+				m_adapter = (m_target.membank == nullptr) ? &devcb_write_base::write_noop_adapter : &devcb_write_base::write_membank_adapter;
+				break;
+
 			case CALLBACK_LOG:
 				m_adapter = &devcb_write_base::write_logged_adapter;
 				break;
@@ -430,12 +516,26 @@ void devcb_write_base::resolve()
 				resolve_inputline();
 				m_adapter = &devcb_write_base::write_inputline_adapter;
 				break;
+
+			case CALLBACK_ASSERTLINE:
+				resolve_inputline();
+				m_adapter = &devcb_write_base::write_assertline_adapter;
+				break;
+
+			case CALLBACK_CLEARLINE:
+				resolve_inputline();
+				m_adapter = &devcb_write_base::write_clearline_adapter;
+				break;
 		}
 	}
 	catch (binding_type_exception &binderr)
 	{
 		throw emu_fatalerror("devcb_write: Error performing a late bind of type %s to %s (name=%s)\n", binderr.m_actual_type.name(), binderr.m_target_type.name(), name);
 	}
+
+	// resolve callback chain recursively
+	if (m_chain != nullptr)
+		m_chain->resolve();
 }
 
 
@@ -515,7 +615,7 @@ void devcb_write_base::write64_adapter(address_space &space, offs_t offset, u64
 
 
 //-------------------------------------------------
-//  write_ioport - write from an I/O port
+//  write_ioport_adapter - write to an I/O port
 //-------------------------------------------------
 
 void devcb_write_base::write_ioport_adapter(address_space &space, offs_t offset, u64 data, u64 mask)
@@ -526,13 +626,25 @@ void devcb_write_base::write_ioport_adapter(address_space &space, offs_t offset,
 
 
 //-------------------------------------------------
-//  write_logged_adapter - logging unresolved
-//  adapter
+//  write_membank_adapter - switch a memory bank
+//-------------------------------------------------
+
+void devcb_write_base::write_membank_adapter(address_space &space, offs_t offset, u64 data, u64 mask)
+{
+	if (m_target.membank)
+		m_target.membank->set_entry(unshift_mask_xor(data));
+}
+
+
+//-------------------------------------------------
+//  write_logged_adapter - log write if masked
+//  value is nonzero
 //-------------------------------------------------
 
 void devcb_write_base::write_logged_adapter(address_space &space, offs_t offset, u64 data, u64 mask)
 {
-	m_device.logerror("%s: unresolved devcb write\n", m_device.machine().describe_context());
+	if (unshift_mask_xor(data) != 0)
+		m_device.logerror("%s: %s\n", m_device.machine().describe_context(), m_target_tag);
 }
 
 
@@ -547,7 +659,7 @@ void devcb_write_base::write_noop_adapter(address_space &space, offs_t offset, u
 
 
 //-------------------------------------------------
-//  write_inputline_adapter - write to an device's
+//  write_inputline_adapter - write to a device's
 //  input line
 //-------------------------------------------------
 
@@ -555,3 +667,27 @@ void devcb_write_base::write_inputline_adapter(address_space &space, offs_t offs
 {
 	m_target.device->execute().set_input_line(m_target_int, unshift_mask_xor(data) & 1);
 }
+
+
+//-------------------------------------------------
+//  write_assertline_adapter - write to a device's
+//  input line
+//-------------------------------------------------
+
+void devcb_write_base::write_assertline_adapter(address_space &space, offs_t offset, u64 data, u64 mask)
+{
+	if (unshift_mask_xor(data) & 1)
+		m_target.device->execute().set_input_line(m_target_int, ASSERT_LINE);
+}
+
+
+//-------------------------------------------------
+//  write_clearline_adapter - write to a device's
+//  input line
+//-------------------------------------------------
+
+void devcb_write_base::write_clearline_adapter(address_space &space, offs_t offset, u64 data, u64 mask)
+{
+	if (unshift_mask_xor(data) & 1)
+		m_target.device->execute().set_input_line(m_target_int, CLEAR_LINE);
+}
diff --git a/src/emu/devcb.h b/src/emu/devcb.h
index c30f9db..58319bd 100644
--- a/src/emu/devcb.h
+++ b/src/emu/devcb.h
@@ -25,9 +25,12 @@
 // wrappers for ioports, constants, and loggers
 #define DEVCB_NOOP devcb_base::null_desc()
 #define DEVCB_IOPORT(_tag) devcb_base::ioport_desc(_tag)
+#define DEVCB_MEMBANK(_tag) devcb_base::membank_desc(_tag)
 #define DEVCB_CONSTANT(_value) devcb_base::constant_desc(_value)
-#define DEVCB_LOGGER(_string, _value) devcb_base::logger_desc(_string, _value)
+#define DEVCB_LOGGER(_string) devcb_base::logger_desc(_string)
 #define DEVCB_INPUTLINE(_tag, _line) devcb_base::inputline_desc(_tag, _line)
+#define DEVCB_ASSERTLINE(_tag, _line) devcb_base::assertline_desc(_tag, _line)
+#define DEVCB_CLEARLINE(_tag, _line) devcb_base::clearline_desc(_tag, _line)
 #define DEVCB_VCC DEVCB_CONSTANT(1)
 #define DEVCB_GND DEVCB_CONSTANT(0)
 
@@ -62,10 +65,14 @@
 // machine config helpers to add shift, mask, or address space configuration
 #define MCFG_DEVCB_RSHIFT(_shift) devcb->set_rshift(_shift);
 #define MCFG_DEVCB_MASK(_mask) devcb->set_mask(_mask);
+#define MCFG_DEVCB_BIT(_bit) devcb->set_rshift(-(_bit)).set_mask(1ULL << (_bit));
 #define MCFG_DEVCB_XOR(_xor) devcb->set_xor(_xor);
 #define MCFG_DEVCB_INVERT devcb->set_xor(~u64(0));
 #define MCFG_DEVCB_ADDRESS_SPACE(_device, _spacenum) devcb->set_space(_device, _spacenum);
 
+// machine config helpers for chaining callbacks
+#define MCFG_DEVCB_CHAIN_INPUT(_desc) devcb = &downcast<devcb_read_base &>(*devcb).chain_alloc().set_callback(DEVCB_##_desc);
+#define MCFG_DEVCB_CHAIN_OUTPUT(_desc) devcb = &downcast<devcb_write_base &>(*devcb).chain_alloc().set_callback(DEVCB_##_desc);
 
 
 //**************************************************************************
@@ -92,13 +99,17 @@ protected:
 		CALLBACK_32,
 		CALLBACK_64,
 		CALLBACK_IOPORT,
+		CALLBACK_MEMBANK,
 		CALLBACK_LOG,
 		CALLBACK_CONSTANT,
-		CALLBACK_INPUTLINE
+		CALLBACK_INPUTLINE,
+		CALLBACK_ASSERTLINE,
+		CALLBACK_CLEARLINE
 	};
 
 	// construction/destruction
 	devcb_base(device_t &device, u64 defmask);
+	virtual ~devcb_base();
 
 public:
 	// getters
@@ -124,6 +135,13 @@ public:
 		const char *m_tag;
 	};
 
+	class membank_desc
+	{
+	public:
+		membank_desc(const char *tag) { m_tag = tag; }
+		const char *m_tag;
+	};
+
 	class constant_desc
 	{
 	public:
@@ -134,9 +152,8 @@ public:
 	class logger_desc
 	{
 	public:
-		logger_desc(const char *string, u64 value = 0) { m_string = string; m_value = value; }
+		logger_desc(const char *string) { m_string = string; }
 		const char *m_string;
-		u64 m_value;
 	};
 
 	class inputline_desc
@@ -147,20 +164,40 @@ public:
 		int m_inputnum;
 	};
 
+	class assertline_desc
+	{
+	public:
+		assertline_desc(const char *tag, int inputnum) { m_tag = tag; m_inputnum = inputnum; }
+		const char *m_tag;
+		int m_inputnum;
+	};
+
+	class clearline_desc
+	{
+	public:
+		clearline_desc(const char *tag, int inputnum) { m_tag = tag; m_inputnum = inputnum; }
+		const char *m_tag;
+		int m_inputnum;
+	};
+
 	// shared callback setters
 	devcb_base &set_callback(null_desc null) { reset(CALLBACK_NONE); return *this; }
 	devcb_base &set_callback(ioport_desc ioport) { reset(CALLBACK_IOPORT); m_target_tag = ioport.m_tag; return *this; }
+	devcb_base &set_callback(membank_desc membank) { reset(CALLBACK_MEMBANK); m_target_tag = membank.m_tag; return *this; }
 	devcb_base &set_callback(constant_desc constant) { reset(CALLBACK_CONSTANT); m_target_int = constant.m_value; return *this; }
-	devcb_base &set_callback(logger_desc logger) { reset(CALLBACK_LOG); m_target_int = logger.m_value; m_target_tag = logger.m_string; return *this; }
-	devcb_base &set_callback(inputline_desc inputline) { reset(CALLBACK_INPUTLINE); m_target_tag = inputline.m_tag; m_target_int = inputline.m_inputnum; return *this; }
+	devcb_base &set_callback(logger_desc logger) { reset(CALLBACK_LOG); m_target_tag = logger.m_string; return *this; }
+	void reset() { reset(CALLBACK_NONE); }
 
 protected:
 	// internal helpers
+	inline u64 shift_mask(u64 value) const { return ((m_rshift < 0) ? (value << -m_rshift) : (value >> m_rshift)) & m_mask; }
 	inline u64 shift_mask_xor(u64 value) const { return (((m_rshift < 0) ? (value << -m_rshift) : (value >> m_rshift)) ^ m_xor) & m_mask; }
 	inline u64 unshift_mask(u64 value) const { return (m_rshift < 0) ? ((value & m_mask) >> -m_rshift) : ((value & m_mask) << m_rshift); }
 	inline u64 unshift_mask_xor(u64 value) const { return (m_rshift < 0) ? (((value ^ m_xor) & m_mask) >> -m_rshift) : (((value ^ m_xor) & m_mask) << m_rshift); }
-	void reset(callback_type type = CALLBACK_NONE);
+	void reset(callback_type type);
+	virtual void devcb_reset() = 0;
 	void resolve_ioport();
+	void resolve_membank();
 	void resolve_inputline();
 	void resolve_space();
 
@@ -170,6 +207,7 @@ protected:
 		void *              ptr;
 		device_t *          device;
 		ioport_port *       ioport;
+		memory_bank *       membank;
 	};
 
 	// configuration
@@ -185,6 +223,7 @@ protected:
 	callback_target     m_target;               // resolved pointer to target object
 	int                 m_rshift;               // right shift to apply to data read
 	u64                 m_mask;                 // mask to apply to data read
+	const u64           m_defmask;              // default mask
 	u64                 m_xor;                  // XOR to apply to data read
 };
 
@@ -205,6 +244,7 @@ public:
 	devcb_base &set_callback(read16_delegate func) { reset(CALLBACK_16); m_read16 = func; return *this; }
 	devcb_base &set_callback(read32_delegate func) { reset(CALLBACK_32); m_read32 = func; return *this; }
 	devcb_base &set_callback(read64_delegate func) { reset(CALLBACK_64); m_read64 = func; return *this; }
+	devcb_read_base &chain_alloc();
 
 	// resolution
 	void resolve();
@@ -212,8 +252,10 @@ public:
 
 protected:
 	// internal helpers
-	void reset(callback_type type = CALLBACK_NONE);
+	virtual void devcb_reset() override;
+	inline u64 read(address_space &space, offs_t offset, u64 mask);
 
+private:
 	// adapters
 	u64 read_unresolved_adapter(address_space &space, offs_t offset, u64 mask);
 	u64 read_line_adapter(address_space &space, offs_t offset, u64 mask);
@@ -235,6 +277,7 @@ protected:
 	// derived state
 	typedef u64 (devcb_read_base::*adapter_func)(address_space &, offs_t, u64);
 	adapter_func        m_adapter;              // actual callback to invoke
+	std::unique_ptr<devcb_read_base> m_chain;   // next callback for chained input
 };
 
 
@@ -254,6 +297,10 @@ public:
 	devcb_base &set_callback(write16_delegate func) { reset(CALLBACK_16); m_write16 = func; return *this; }
 	devcb_base &set_callback(write32_delegate func) { reset(CALLBACK_32); m_write32 = func; return *this; }
 	devcb_base &set_callback(write64_delegate func) { reset(CALLBACK_64); m_write64 = func; return *this; }
+	devcb_base &set_callback(inputline_desc inputline) { reset(CALLBACK_INPUTLINE); m_target_tag = inputline.m_tag; m_target_int = inputline.m_inputnum; return *this; }
+	devcb_base &set_callback(assertline_desc inputline) { reset(CALLBACK_ASSERTLINE); m_target_tag = inputline.m_tag; m_target_int = inputline.m_inputnum; return *this; }
+	devcb_base &set_callback(clearline_desc inputline) { reset(CALLBACK_CLEARLINE); m_target_tag = inputline.m_tag; m_target_int = inputline.m_inputnum; return *this; }
+	devcb_write_base &chain_alloc();
 
 	// resolution
 	void resolve();
@@ -261,8 +308,10 @@ public:
 
 protected:
 	// internal helpers
-	void reset(callback_type type = CALLBACK_NONE);
+	virtual void devcb_reset() override;
+	inline void write(address_space &space, offs_t offset, u64 data, u64 mask);
 
+private:
 	// adapters
 	void write_unresolved_adapter(address_space &space, offs_t offset, u64 data, u64 mask);
 	void write_line_adapter(address_space &space, offs_t offset, u64 data, u64 mask);
@@ -271,9 +320,12 @@ protected:
 	void write32_adapter(address_space &space, offs_t offset, u64 data, u64 mask);
 	void write64_adapter(address_space &space, offs_t offset, u64 data, u64 mask);
 	void write_ioport_adapter(address_space &space, offs_t offset, u64 data, u64 mask);
+	void write_membank_adapter(address_space &space, offs_t offset, u64 data, u64 mask);
 	void write_logged_adapter(address_space &space, offs_t offset, u64 data, u64 mask);
 	void write_noop_adapter(address_space &space, offs_t offset, u64 data, u64 mask);
 	void write_inputline_adapter(address_space &space, offs_t offset, u64 data, u64 mask);
+	void write_assertline_adapter(address_space &space, offs_t offset, u64 data, u64 mask);
+	void write_clearline_adapter(address_space &space, offs_t offset, u64 data, u64 mask);
 
 	// configuration
 	write_line_delegate m_writeline;            // copy of registered line writer
@@ -285,6 +337,7 @@ protected:
 	// derived state
 	typedef void (devcb_write_base::*adapter_func)(address_space &, offs_t, u64, u64);
 	adapter_func        m_adapter;              // actual callback to invoke
+	std::unique_ptr<devcb_write_base> m_chain;  // next callback for chained output
 };
 
 
@@ -294,8 +347,8 @@ class devcb_read_line : public devcb_read_base
 {
 public:
 	devcb_read_line(device_t &device) : devcb_read_base(device, 0xff) { }
-	int operator()() { return (this->*m_adapter)(*m_space, 0, 0xffU) & 1; }
-	int operator()(address_space &space) { return (this->*m_adapter)((m_space_tag != nullptr) ? *m_space : space, 0, 0xffU) & 1; }
+	int operator()() { return read(*m_space, 0, 0xffU) & 1; }
+	int operator()(address_space &space) { return read((m_space_tag != nullptr) ? *m_space : space, 0, 0xffU) & 1; }
 };
 
 
@@ -305,8 +358,8 @@ class devcb_read8 : public devcb_read_base
 {
 public:
 	devcb_read8(device_t &device) : devcb_read_base(device, 0xff) { }
-	u8 operator()(offs_t offset = 0, u8 mask = 0xff) { return (this->*m_adapter)(*m_space, offset, mask) & mask; }
-	u8 operator()(address_space &space, offs_t offset = 0, u8 mask = 0xff) { return (this->*m_adapter)((m_space_tag != nullptr) ? *m_space : space, offset, mask) & mask; }
+	u8 operator()(offs_t offset = 0, u8 mask = 0xff) { return read(*m_space, offset, mask) & mask; }
+	u8 operator()(address_space &space, offs_t offset = 0, u8 mask = 0xff) { return read((m_space_tag != nullptr) ? *m_space : space, offset, mask) & mask; }
 };
 
 
@@ -316,8 +369,8 @@ class devcb_read16 : public devcb_read_base
 {
 public:
 	devcb_read16(device_t &device) : devcb_read_base(device, 0xffff) { }
-	u16 operator()(offs_t offset = 0, u16 mask = 0xffff) { return (this->*m_adapter)(*m_space, offset, mask) & mask; }
-	u16 operator()(address_space &space, offs_t offset = 0, u16 mask = 0xffff) { return (this->*m_adapter)((m_space_tag != nullptr) ? *m_space : space, offset, mask) & mask; }
+	u16 operator()(offs_t offset = 0, u16 mask = 0xffff) { return read(*m_space, offset, mask) & mask; }
+	u16 operator()(address_space &space, offs_t offset = 0, u16 mask = 0xffff) { return read((m_space_tag != nullptr) ? *m_space : space, offset, mask) & mask; }
 };
 
 
@@ -327,8 +380,8 @@ class devcb_read32 : public devcb_read_base
 {
 public:
 	devcb_read32(device_t &device) : devcb_read_base(device, 0xffffffff) { }
-	u32 operator()(offs_t offset = 0, u32 mask = 0xffffffff) { return (this->*m_adapter)(*m_space, offset, mask) & mask; }
-	u32 operator()(address_space &space, offs_t offset = 0, u32 mask = 0xffffffff) { return (this->*m_adapter)((m_space_tag != nullptr) ? *m_space : space, offset, mask) & mask; }
+	u32 operator()(offs_t offset = 0, u32 mask = 0xffffffff) { return read(*m_space, offset, mask) & mask; }
+	u32 operator()(address_space &space, offs_t offset = 0, u32 mask = 0xffffffff) { return read((m_space_tag != nullptr) ? *m_space : space, offset, mask) & mask; }
 };
 
 
@@ -338,8 +391,8 @@ class devcb_read64 : public devcb_read_base
 {
 public:
 	devcb_read64(device_t &device) : devcb_read_base(device, 0xffffffffffffffffU) { }
-	u64 operator()(offs_t offset = 0, u64 mask = 0xffffffffffffffffU) { return (this->*m_adapter)(*m_space, offset, mask) & mask; }
-	u64 operator()(address_space &space, offs_t offset = 0, u64 mask = 0xffffffffffffffffU) { return (this->*m_adapter)((m_space_tag != nullptr) ? *m_space : space, offset, mask) & mask; }
+	u64 operator()(offs_t offset = 0, u64 mask = 0xffffffffffffffffU) { return read(*m_space, offset, mask) & mask; }
+	u64 operator()(address_space &space, offs_t offset = 0, u64 mask = 0xffffffffffffffffU) { return read((m_space_tag != nullptr) ? *m_space : space, offset, mask) & mask; }
 };
 
 
@@ -349,8 +402,8 @@ class devcb_write_line : public devcb_write_base
 {
 public:
 	devcb_write_line(device_t &device) : devcb_write_base(device, 0xff) { }
-	void operator()(int state) { (this->*m_adapter)(*m_space, 0, state & 1, 0xffU); }
-	void operator()(address_space &space, int state) { (this->*m_adapter)((m_space_tag != nullptr) ? *m_space : space, 0, state & 1, 0xffU); }
+	void operator()(int state) { write(*m_space, 0, state & 1, 0xffU); }
+	void operator()(address_space &space, int state) { write((m_space_tag != nullptr) ? *m_space : space, 0, state & 1, 0xffU); }
 };
 
 
@@ -360,9 +413,9 @@ class devcb_write8 : public devcb_write_base
 {
 public:
 	devcb_write8(device_t &device) : devcb_write_base(device, 0xff) { }
-	void operator()(u8 data, u8 mask = 0xff) { (this->*m_adapter)(*m_space, 0, data, mask); }
-	void operator()(offs_t offset, u8 data, u8 mask = 0xff) { (this->*m_adapter)(*m_space, offset, data, mask); }
-	void operator()(address_space &space, offs_t offset, u8 data, u8 mask = 0xff) { (this->*m_adapter)((m_space_tag != nullptr) ? *m_space : space, offset, data, mask); }
+	void operator()(u8 data, u8 mask = 0xff) { write(*m_space, 0, data, mask); }
+	void operator()(offs_t offset, u8 data, u8 mask = 0xff) { write(*m_space, offset, data, mask); }
+	void operator()(address_space &space, offs_t offset, u8 data, u8 mask = 0xff) { write((m_space_tag != nullptr) ? *m_space : space, offset, data, mask); }
 };
 
 
@@ -372,9 +425,9 @@ class devcb_write16 : public devcb_write_base
 {
 public:
 	devcb_write16(device_t &device) : devcb_write_base(device, 0xffff) { }
-	void operator()(u16 data, u16 mask = 0xffff) { (this->*m_adapter)(*m_space, 0, data, mask); }
-	void operator()(offs_t offset, u16 data, u16 mask = 0xffff) { (this->*m_adapter)(*m_space, offset, data, mask); }
-	void operator()(address_space &space, offs_t offset, u16 data, u16 mask = 0xffff) { (this->*m_adapter)((m_space_tag != nullptr) ? *m_space : space, offset, data, mask); }
+	void operator()(u16 data, u16 mask = 0xffff) { write(*m_space, 0, data, mask); }
+	void operator()(offs_t offset, u16 data, u16 mask = 0xffff) { write(*m_space, offset, data, mask); }
+	void operator()(address_space &space, offs_t offset, u16 data, u16 mask = 0xffff) { write((m_space_tag != nullptr) ? *m_space : space, offset, data, mask); }
 };
 
 
@@ -384,9 +437,9 @@ class devcb_write32 : public devcb_write_base
 {
 public:
 	devcb_write32(device_t &device) : devcb_write_base(device, 0xffffffff) { }
-	void operator()(u32 data, u32 mask = 0xffffffff) { (this->*m_adapter)(*m_space, 0, data, mask); }
-	void operator()(offs_t offset, u32 data, u32 mask = 0xffffffff) { (this->*m_adapter)(*m_space, offset, data, mask); }
-	void operator()(address_space &space, offs_t offset, u32 data, u32 mask = 0xffffffff) { (this->*m_adapter)((m_space_tag != nullptr) ? *m_space : space, offset, data, mask); }
+	void operator()(u32 data, u32 mask = 0xffffffff) { write(*m_space, 0, data, mask); }
+	void operator()(offs_t offset, u32 data, u32 mask = 0xffffffff) { write(*m_space, offset, data, mask); }
+	void operator()(address_space &space, offs_t offset, u32 data, u32 mask = 0xffffffff) { write((m_space_tag != nullptr) ? *m_space : space, offset, data, mask); }
 };
 
 
@@ -396,10 +449,40 @@ class devcb_write64 : public devcb_write_base
 {
 public:
 	devcb_write64(device_t &device) : devcb_write_base(device, 0xffffffffffffffffU) { }
-	void operator()(u64 data, u64 mask = 0xffffffffffffffffU) { (this->*m_adapter)(*m_space, 0, data, mask); }
-	void operator()(offs_t offset, u64 data, u64 mask = 0xffffffffffffffffU) { (this->*m_adapter)(*m_space, offset, data, mask); }
-	void operator()(address_space &space, offs_t offset, u64 data, u64 mask = 0xffffffffffffffffU) { (this->*m_adapter)((m_space_tag != nullptr) ? *m_space : space, offset, data, mask); }
+	void operator()(u64 data, u64 mask = 0xffffffffffffffffU) { write(*m_space, 0, data, mask); }
+	void operator()(offs_t offset, u64 data, u64 mask = 0xffffffffffffffffU) { write(*m_space, offset, data, mask); }
+	void operator()(address_space &space, offs_t offset, u64 data, u64 mask = 0xffffffffffffffffU) { write((m_space_tag != nullptr) ? *m_space : space, offset, data, mask); }
 };
 
 
+
+//**************************************************************************
+//  INLINE FUNCTIONS
+//**************************************************************************
+
+//-------------------------------------------------
+//  read - generic read callback dispatch
+//-------------------------------------------------
+
+inline u64 devcb_read_base::read(address_space &space, offs_t offset, u64 mask)
+{
+	u64 result = (this->*m_adapter)(space, offset, mask);
+	if (m_chain != nullptr)
+		result |= m_chain->read(space, offset, mask);
+	return result;
+}
+
+
+//-------------------------------------------------
+//  write - generic write callback dispatch
+//-------------------------------------------------
+
+inline void devcb_write_base::write(address_space &space, offs_t offset, u64 data, u64 mask)
+{
+	(this->*m_adapter)(space, offset, data, mask);
+	if (m_chain != nullptr)
+		m_chain->write(space, offset, data, mask);
+}
+
+
 #endif  /* MAME_EMU_DEVCB_H */
diff --git a/src/emu/dimemory.cpp b/src/emu/dimemory.cpp
index e42ad28..cdb234c 100644
--- a/src/emu/dimemory.cpp
+++ b/src/emu/dimemory.cpp
@@ -182,52 +182,6 @@ bool device_memory_interface::memory_translate(address_spacenum spacenum, int in
 
 
 //-------------------------------------------------
-//  memory_read - perform internal memory
-//  operations that bypass the memory system;
-//  designed to be overridden by the actual device
-//  implementation if internal read operations are
-//  handled by bypassing the memory system
-//-------------------------------------------------
-
-bool device_memory_interface::memory_read(address_spacenum spacenum, offs_t offset, int size, u64 &value)
-{
-	// by default, we don't do anything
-	return false;
-}
-
-
-//-------------------------------------------------
-//  memory_write - perform internal memory
-//  operations that bypass the memory system;
-//  designed to be overridden by the actual device
-//  implementation if internal write operations are
-//  handled by bypassing the memory system
-//-------------------------------------------------
-
-bool device_memory_interface::memory_write(address_spacenum spacenum, offs_t offset, int size, u64 value)
-{
-	// by default, we don't do anything
-	return false;
-}
-
-
-//-------------------------------------------------
-//  memory_readop - perform internal memory
-//  operations that bypass the memory system;
-//  designed to be overridden by the actual device
-//  implementation if internal opcode fetching
-//  operations are handled by bypassing the memory
-//  system
-//-------------------------------------------------
-
-bool device_memory_interface::memory_readop(offs_t offset, int size, u64 &value)
-{
-	// by default, we don't do anything
-	return false;
-}
-
-
-//-------------------------------------------------
 //  interface_validity_check - perform validity
 //  checks on the memory configuration
 //-------------------------------------------------
diff --git a/src/emu/dimemory.h b/src/emu/dimemory.h
index c5a3226..342c1f0 100644
--- a/src/emu/dimemory.h
+++ b/src/emu/dimemory.h
@@ -99,11 +99,6 @@ public:
 	// address translation
 	bool translate(address_spacenum spacenum, int intention, offs_t &address) { return memory_translate(spacenum, intention, address); }
 
-	// read/write access
-	bool read(address_spacenum spacenum, offs_t offset, int size, u64 &value) { return memory_read(spacenum, offset, size, value); }
-	bool write(address_spacenum spacenum, offs_t offset, int size, u64 value) { return memory_write(spacenum, offset, size, value); }
-	bool readop(offs_t offset, int size, u64 &value) { return memory_readop(offset, size, value); }
-
 	// deliberately ambiguous functions; if you have the memory interface
 	// just use it
 	device_memory_interface &memory() { return *this; }
@@ -114,9 +109,6 @@ protected:
 
 	// optional operation overrides
 	virtual bool memory_translate(address_spacenum spacenum, int intention, offs_t &address);
-	virtual bool memory_read(address_spacenum spacenum, offs_t offset, int size, u64 &value);
-	virtual bool memory_write(address_spacenum spacenum, offs_t offset, int size, u64 value);
-	virtual bool memory_readop(offs_t offset, int size, u64 &value);
 
 	// interface-level overrides
 	virtual void interface_validity_check(validity_checker &valid) const override;
diff --git a/src/emu/dispatch.cpp b/src/emu/dispatch.cpp
deleted file mode 100644
index b82fb85..0000000
--- a/src/emu/dispatch.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Olivier Galibert
-
-#include "emu.h"
-
-const device_type DEVCB_LINE_DISPATCH_2 = &device_creator<devcb_line_dispatch_device<2> >;
-const device_type DEVCB_LINE_DISPATCH_3 = &device_creator<devcb_line_dispatch_device<3> >;
-const device_type DEVCB_LINE_DISPATCH_4 = &device_creator<devcb_line_dispatch_device<4> >;
-const device_type DEVCB_LINE_DISPATCH_5 = &device_creator<devcb_line_dispatch_device<5> >;
-const device_type DEVCB_LINE_DISPATCH_6 = &device_creator<devcb_line_dispatch_device<6> >;
-
-template<> devcb_line_dispatch_device<2>::devcb_line_dispatch_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
-	device_t(mconfig, DEVCB_LINE_DISPATCH_2, "Line dispatcher (2 slots)", tag, owner, clock, "devcb_line_dispatch", __FILE__)
-{
-	init_fwd();
-}
-
-template<> devcb_line_dispatch_device<3>::devcb_line_dispatch_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
-	device_t(mconfig, DEVCB_LINE_DISPATCH_3, "Line dispatcher (3 slots)", tag, owner, clock, "devcb_line_dispatch", __FILE__)
-{
-	init_fwd();
-}
-
-template<> devcb_line_dispatch_device<4>::devcb_line_dispatch_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
-	device_t(mconfig, DEVCB_LINE_DISPATCH_4, "Line dispatcher (4 slots)", tag, owner, clock, "devcb_line_dispatch", __FILE__)
-{
-	init_fwd();
-}
-
-template<> devcb_line_dispatch_device<5>::devcb_line_dispatch_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
-	device_t(mconfig, DEVCB_LINE_DISPATCH_5, "Line dispatcher (5 slots)", tag, owner, clock, "devcb_line_dispatch", __FILE__)
-{
-	init_fwd();
-}
-
-template<> devcb_line_dispatch_device<6>::devcb_line_dispatch_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
-	device_t(mconfig, DEVCB_LINE_DISPATCH_6, "Line dispatcher (6 slots)", tag, owner, clock, "devcb_line_dispatch", __FILE__)
-{
-	init_fwd();
-}
diff --git a/src/emu/dispatch.h b/src/emu/dispatch.h
deleted file mode 100644
index 26be42e..0000000
--- a/src/emu/dispatch.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Olivier Galibert
-/***************************************************************************
-
-    dispatch.h
-
-    Signal dispatching devices.
-
-***************************************************************************/
-
-#pragma once
-
-#ifndef __EMU_H__
-#error Dont include this file directly; include emu.h instead.
-#endif
-
-#ifndef MAME_EMU_DISPATCH_H
-#define MAME_EMU_DISPATCH_H
-
-#define MCFG_LINE_DISPATCH_ADD(_tag, _count) \
-	MCFG_DEVICE_ADD(_tag, DEVCB_LINE_DISPATCH_ ## _count, 0)
-
-#define MCFG_LINE_DISPATCH_FWD_CB(_entry, _count, _devcb) \
-	devcb = &devcb_line_dispatch_device<_count>::set_fwd_cb(*device, _entry, DEVCB_##_devcb);
-
-extern const device_type DEVCB_LINE_DISPATCH_2;
-extern const device_type DEVCB_LINE_DISPATCH_3;
-extern const device_type DEVCB_LINE_DISPATCH_4;
-extern const device_type DEVCB_LINE_DISPATCH_5;
-extern const device_type DEVCB_LINE_DISPATCH_6;
-
-template<int N> class devcb_line_dispatch_device : public device_t {
-public:
-	devcb_line_dispatch_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
-		device_t(mconfig, DEVCB_LINE_DISPATCH_2, "DEVCB_LINE_DISPATCH_2", tag, owner, clock, "devcb_line_dispatch_2", __FILE__) { }
-
-	void init_fwd() {
-		for(auto & elem : fwd_cb)
-			elem = new devcb_write_line(*this);
-	}
-
-	virtual ~devcb_line_dispatch_device() {
-		for(auto & elem : fwd_cb)
-			delete elem;
-	}
-
-	template<class _Object> static devcb_base &set_fwd_cb(device_t &device, int entry, _Object object) { return downcast<devcb_line_dispatch_device<N> &>(device).fwd_cb[entry]->set_callback(object); }
-
-	WRITE_LINE_MEMBER( in_w ) {
-		for(auto & elem : fwd_cb)
-			(*(elem))(state);
-	}
-
-protected:
-	virtual void device_start() override {
-		for(auto & elem : fwd_cb)
-			elem->resolve_safe();
-	}
-
-private:
-	devcb_write_line *fwd_cb[N];
-};
-
-#endif // MAME_EMU_DISPATCH_H
diff --git a/src/emu/drivers/xtal.h b/src/emu/drivers/xtal.h
index 4f370d3..d6e341d 100644
--- a/src/emu/drivers/xtal.h
+++ b/src/emu/drivers/xtal.h
@@ -173,6 +173,7 @@ enum
 	XTAL_21_3MHz        = 21300000,
 	XTAL_21_4772MHz     = 21477272,     /* BMC bowling, some Data East 90's games, Vtech Socrates; (6x NTSC subcarrier) */
 	XTAL_22MHz          = 22000000,
+	XTAL_22_3210MHz     = 22321000,     /* Apple LaserWriter II NT */
 	XTAL_22_1184MHz     = 22118400,     /* Amusco Poker */
 	XTAL_23_9616MHz     = 23961600,     /* Osborne 4 (Vixen) */
 	XTAL_24MHz          = 24000000,     /* Mario, 80's Data East games, 80's Konami games */
diff --git a/src/emu/emu.h b/src/emu/emu.h
index de2105f..65a45a4 100644
--- a/src/emu/emu.h
+++ b/src/emu/emu.h
@@ -110,7 +110,6 @@ typedef device_t * (*machine_config_constructor)(machine_config &config, device_
 
 // generic helpers
 #include "devcb.h"
-#include "dispatch.h"
 #include "drivers/xtal.h"
 #include "bookkeeping.h"
 #include "video/generic.h"
diff --git a/src/emu/image.cpp b/src/emu/image.cpp
index b7e5ddd..29d8424 100644
--- a/src/emu/image.cpp
+++ b/src/emu/image.cpp
@@ -76,7 +76,7 @@ image_manager::image_manager(running_machine &machine)
 		}
 	}
 
-	machine.configuration().config_register("image_directories", config_saveload_delegate(&image_manager::config_load, this), config_saveload_delegate(&image_manager::config_save, this));
+	machine.configuration().config_register("image_directories", config_load_delegate(&image_manager::config_load, this), config_save_delegate(&image_manager::config_save, this));
 }
 
 //-------------------------------------------------
@@ -95,24 +95,21 @@ void image_manager::unload_all()
 	}
 }
 
-void image_manager::config_load(config_type cfg_type, xml_data_node *parentnode)
+void image_manager::config_load(config_type cfg_type, util::xml::data_node const *parentnode)
 {
-	xml_data_node const *node;
-	const char *dev_instance;
-	const char *working_directory;
-
-	if ((cfg_type == config_type::CONFIG_TYPE_GAME) && (parentnode != nullptr))
+	if ((cfg_type == config_type::GAME) && (parentnode != nullptr))
 	{
-		for (node = parentnode->get_child("device"); node; node = node->get_next_sibling("device"))
+		for (util::xml::data_node const *node = parentnode->get_child("device"); node; node = node->get_next_sibling("device"))
 		{
-			dev_instance = node->get_attribute_string("instance", nullptr);
+			const char *const dev_instance = node->get_attribute_string("instance", nullptr);
 
 			if ((dev_instance != nullptr) && (dev_instance[0] != '\0'))
 			{
 				for (device_image_interface &image : image_interface_iterator(machine().root_device()))
 				{
-					if (!strcmp(dev_instance, image.instance_name())) {
-						working_directory = node->get_attribute_string("directory", nullptr);
+					if (!strcmp(dev_instance, image.instance_name()))
+					{
+						const char *const working_directory = node->get_attribute_string("directory", nullptr);
 						if (working_directory != nullptr)
 							image.set_working_directory(working_directory);
 					}
@@ -127,19 +124,16 @@ void image_manager::config_load(config_type cfg_type, xml_data_node *parentnode)
     directories to the configuration file
 -------------------------------------------------*/
 
-void image_manager::config_save(config_type cfg_type, xml_data_node *parentnode)
+void image_manager::config_save(config_type cfg_type, util::xml::data_node *parentnode)
 {
-	xml_data_node *node;
-	const char *dev_instance;
-
 	/* only care about game-specific data */
-	if (cfg_type == config_type::CONFIG_TYPE_GAME)
+	if (cfg_type == config_type::GAME)
 	{
 		for (device_image_interface &image : image_interface_iterator(machine().root_device()))
 		{
-			dev_instance = image.instance_name();
+			const char *const dev_instance = image.instance_name();
 
-			node = parentnode->add_child("device", nullptr);
+			util::xml::data_node *const node = parentnode->add_child("device", nullptr);
 			if (node != nullptr)
 			{
 				node->set_attribute("instance", dev_instance);
diff --git a/src/emu/image.h b/src/emu/image.h
index 4a9e55e..b0cc5f6 100644
--- a/src/emu/image.h
+++ b/src/emu/image.h
@@ -8,10 +8,10 @@
 
 ***************************************************************************/
 
-#pragma once
+#ifndef MAME_EMU_IMAGE_H
+#define MAME_EMU_IMAGE_H
 
-#ifndef __IMAGE_H__
-#define __IMAGE_H__
+#pragma once
 
 // ======================> image_manager
 
@@ -27,8 +27,8 @@ public:
 	// getters
 	running_machine &machine() const { return m_machine; }
 private:
-	void config_load(config_type cfg_type, xml_data_node *parentnode);
-	void config_save(config_type cfg_type, xml_data_node *parentnode);
+	void config_load(config_type cfg_type, util::xml::data_node const *parentnode);
+	void config_save(config_type cfg_type, util::xml::data_node *parentnode);
 
 	void options_extract();
 	int write_config(emu_options &options, const char *filename, const game_driver *gamedrv);
@@ -37,4 +37,4 @@ private:
 	running_machine &   m_machine;                  // reference to our machine
 };
 
-#endif /* __IMAGE_H__ */
+#endif /* MAME_EMU_IMAGE_H */
diff --git a/src/emu/ioport.cpp b/src/emu/ioport.cpp
index 5e268ff..6f751a2 100644
--- a/src/emu/ioport.cpp
+++ b/src/emu/ioport.cpp
@@ -1747,7 +1747,7 @@ time_t ioport_manager::initialize()
 	m_natkeyboard = std::make_unique<natural_keyboard>(machine());
 
 	// register callbacks for when we load configurations
-	machine().configuration().config_register("input", config_saveload_delegate(&ioport_manager::load_config, this), config_saveload_delegate(&ioport_manager::save_config, this));
+	machine().configuration().config_register("input", config_load_delegate(&ioport_manager::load_config, this), config_save_delegate(&ioport_manager::save_config, this));
 
 	// open playback and record files if specified
 	time_t basetime = playback_init();
@@ -2080,10 +2080,10 @@ s32 ioport_manager::frame_interpolate(s32 oldval, s32 newval)
 //  data from the XML nodes
 //-------------------------------------------------
 
-void ioport_manager::load_config(config_type cfg_type, xml_data_node *parentnode)
+void ioport_manager::load_config(config_type cfg_type, util::xml::data_node const *parentnode)
 {
 	// in the completion phase, we finish the initialization with the final ports
-	if (cfg_type == config_type::CONFIG_TYPE_FINAL)
+	if (cfg_type == config_type::FINAL)
 	{
 		m_safe_to_read = true;
 		frame_update();
@@ -2094,14 +2094,14 @@ void ioport_manager::load_config(config_type cfg_type, xml_data_node *parentnode
 		return;
 
 	// iterate over all the remap nodes for controller configs only
-	if (cfg_type == config_type::CONFIG_TYPE_CONTROLLER)
+	if (cfg_type == config_type::CONTROLLER)
 		load_remap_table(parentnode);
 
 	// load device map table for controller configs only
-	if (cfg_type == config_type::CONFIG_TYPE_CONTROLLER)
+	if (cfg_type == config_type::CONTROLLER)
 	{
 		std::unique_ptr<devicemap_table_type> devicemap_table = std::make_unique<devicemap_table_type>();
-		for (xml_data_node const *mapdevice_node = parentnode->get_child("mapdevice"); mapdevice_node != nullptr; mapdevice_node = mapdevice_node->get_next_sibling("mapdevice"))
+		for (util::xml::data_node const *mapdevice_node = parentnode->get_child("mapdevice"); mapdevice_node != nullptr; mapdevice_node = mapdevice_node->get_next_sibling("mapdevice"))
 		{
 			const char *devicename = mapdevice_node->get_attribute_string("device", nullptr);
 			const char *controllername = mapdevice_node->get_attribute_string("controller", nullptr);
@@ -2119,7 +2119,7 @@ void ioport_manager::load_config(config_type cfg_type, xml_data_node *parentnode
 	}
 
 	// iterate over all the port nodes
-	for (xml_data_node const *portnode = parentnode->get_child("port"); portnode; portnode = portnode->get_next_sibling("port"))
+	for (util::xml::data_node const *portnode = parentnode->get_child("port"); portnode; portnode = portnode->get_next_sibling("port"))
 	{
 		// get the basic port info from the attributes
 		int player;
@@ -2131,7 +2131,7 @@ void ioport_manager::load_config(config_type cfg_type, xml_data_node *parentnode
 			newseq[seqtype].set(INPUT_CODE_INVALID);
 
 		// loop over new sequences
-		for (xml_data_node const *seqnode = portnode->get_child("newseq"); seqnode; seqnode = seqnode->get_next_sibling("newseq"))
+		for (util::xml::data_node const *seqnode = portnode->get_child("newseq"); seqnode; seqnode = seqnode->get_next_sibling("newseq"))
 		{
 			// with a valid type, parse out the new sequence
 			input_seq_type seqtype = token_to_seq_type(seqnode->get_attribute_string("type", ""));
@@ -2145,7 +2145,7 @@ void ioport_manager::load_config(config_type cfg_type, xml_data_node *parentnode
 		}
 
 		// if we're loading default ports, apply to the defaults
-		if (cfg_type != config_type::CONFIG_TYPE_GAME)
+		if (cfg_type != config_type::GAME)
 			load_default_config(portnode, type, player, newseq);
 		else
 			load_game_config(portnode, type, player, newseq);
@@ -2153,7 +2153,7 @@ void ioport_manager::load_config(config_type cfg_type, xml_data_node *parentnode
 
 	// after applying the controller config, push that back into the backup, since that is
 	// what we will diff against
-	if (cfg_type == config_type::CONFIG_TYPE_CONTROLLER)
+	if (cfg_type == config_type::CONTROLLER)
 		for (input_type_entry &entry : m_typelist)
 			for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; ++seqtype)
 				entry.defseq(seqtype) = entry.seq(seqtype);
@@ -2165,11 +2165,11 @@ void ioport_manager::load_config(config_type cfg_type, xml_data_node *parentnode
 //  global remapping table
 //-------------------------------------------------
 
-void ioport_manager::load_remap_table(xml_data_node const *parentnode)
+void ioport_manager::load_remap_table(util::xml::data_node const *parentnode)
 {
 	// count items first so we can allocate
 	int count = 0;
-	for (xml_data_node const *remapnode = parentnode->get_child("remap"); remapnode != nullptr; remapnode = remapnode->get_next_sibling("remap"))
+	for (util::xml::data_node const *remapnode = parentnode->get_child("remap"); remapnode != nullptr; remapnode = remapnode->get_next_sibling("remap"))
 		count++;
 
 	// if we have some, deal with them
@@ -2181,7 +2181,7 @@ void ioport_manager::load_remap_table(xml_data_node const *parentnode)
 
 		// build up the remap table
 		count = 0;
-		for (xml_data_node const *remapnode = parentnode->get_child("remap"); remapnode != nullptr; remapnode = remapnode->get_next_sibling("remap"))
+		for (util::xml::data_node const *remapnode = parentnode->get_child("remap"); remapnode != nullptr; remapnode = remapnode->get_next_sibling("remap"))
 		{
 			input_code origcode = machine().input().code_from_token(remapnode->get_attribute_string("origcode", ""));
 			input_code newcode = machine().input().code_from_token(remapnode->get_attribute_string("newcode", ""));
@@ -2207,7 +2207,7 @@ void ioport_manager::load_remap_table(xml_data_node const *parentnode)
 //  data to the default mappings
 //-------------------------------------------------
 
-bool ioport_manager::load_default_config(xml_data_node const *portnode, int type, int player, const input_seq *newseq)
+bool ioport_manager::load_default_config(util::xml::data_node const *portnode, int type, int player, const input_seq *newseq)
 {
 	// find a matching port in the list
 	for (input_type_entry &entry : m_typelist)
@@ -2228,7 +2228,7 @@ bool ioport_manager::load_default_config(xml_data_node const *portnode, int type
 //  data to the current set of input ports
 //-------------------------------------------------
 
-bool ioport_manager::load_game_config(xml_data_node const *portnode, int type, int player, const input_seq *newseq)
+bool ioport_manager::load_game_config(util::xml::data_node const *portnode, int type, int player, const input_seq *newseq)
 {
 	// read the mask, index, and defvalue attributes
 	const char *tag = portnode->get_attribute_string("tag", nullptr);
@@ -2292,17 +2292,17 @@ bool ioport_manager::load_game_config(xml_data_node const *portnode, int type, i
 //  port configuration
 //-------------------------------------------------
 
-void ioport_manager::save_config(config_type cfg_type, xml_data_node *parentnode)
+void ioport_manager::save_config(config_type cfg_type, util::xml::data_node *parentnode)
 {
 	// if no parentnode, ignore
 	if (parentnode == nullptr)
 		return;
 
 	// default ports save differently
-	if (cfg_type == config_type::CONFIG_TYPE_DEFAULT)
-		save_default_inputs(parentnode);
+	if (cfg_type == config_type::DEFAULT)
+		save_default_inputs(*parentnode);
 	else
-		save_game_inputs(parentnode);
+		save_game_inputs(*parentnode);
 }
 
 
@@ -2311,7 +2311,7 @@ void ioport_manager::save_config(config_type cfg_type, xml_data_node *parentnode
 //  sequence
 //-------------------------------------------------
 
-void ioport_manager::save_sequence(xml_data_node *parentnode, input_seq_type type, ioport_type porttype, const input_seq &seq)
+void ioport_manager::save_sequence(util::xml::data_node &parentnode, input_seq_type type, ioport_type porttype, const input_seq &seq)
 {
 	// get the string for the sequence
 	std::string seqstring;
@@ -2321,7 +2321,7 @@ void ioport_manager::save_sequence(xml_data_node *parentnode, input_seq_type typ
 		seqstring = machine().input().seq_to_tokens(seq);
 
 	// add the new node
-	xml_data_node *const seqnode = parentnode->add_child("newseq", seqstring.c_str());
+	util::xml::data_node *const seqnode = parentnode.add_child("newseq", seqstring.c_str());
 	if (seqnode != nullptr)
 		seqnode->set_attribute("type", seqtypestrings[type]);
 }
@@ -2354,7 +2354,7 @@ bool ioport_manager::save_this_input_field_type(ioport_type type)
 //  mappings that have changed
 //-------------------------------------------------
 
-void ioport_manager::save_default_inputs(xml_data_node *parentnode)
+void ioport_manager::save_default_inputs(util::xml::data_node &parentnode)
 {
 	// iterate over ports
 	for (input_type_entry &entry : m_typelist)
@@ -2372,7 +2372,7 @@ void ioport_manager::save_default_inputs(xml_data_node *parentnode)
 			if (seqtype < SEQ_TYPE_TOTAL)
 			{
 				// add a new port node
-				xml_data_node *const portnode = parentnode->add_child("port", nullptr);
+				util::xml::data_node *const portnode = parentnode.add_child("port", nullptr);
 				if (portnode != nullptr)
 				{
 					// add the port information and attributes
@@ -2381,7 +2381,7 @@ void ioport_manager::save_default_inputs(xml_data_node *parentnode)
 					// add only the sequences that have changed from the defaults
 					for (input_seq_type type = SEQ_TYPE_STANDARD; type < SEQ_TYPE_TOTAL; ++type)
 						if (entry.seq(type) != entry.defseq(type))
-							save_sequence(portnode, type, entry.type(), entry.seq(type));
+							save_sequence(*portnode, type, entry.type(), entry.seq(type));
 				}
 			}
 		}
@@ -2394,7 +2394,7 @@ void ioport_manager::save_default_inputs(xml_data_node *parentnode)
 //  mappings that have changed
 //-------------------------------------------------
 
-void ioport_manager::save_game_inputs(xml_data_node *parentnode)
+void ioport_manager::save_game_inputs(util::xml::data_node &parentnode)
 {
 	// iterate over ports
 	for (auto &port : m_portlist)
@@ -2426,7 +2426,7 @@ void ioport_manager::save_game_inputs(xml_data_node *parentnode)
 				if (changed)
 				{
 					// add a new port node
-					xml_data_node *portnode = parentnode->add_child("port", nullptr);
+					util::xml::data_node *const portnode = parentnode.add_child("port", nullptr);
 					if (portnode != nullptr)
 					{
 						// add the identifying information and attributes
@@ -2438,7 +2438,7 @@ void ioport_manager::save_game_inputs(xml_data_node *parentnode)
 						// add sequences if changed
 						for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; ++seqtype)
 							if (field.seq(seqtype) != field.defseq(seqtype))
-								save_sequence(portnode, seqtype, field.type(), field.seq(seqtype));
+								save_sequence(*portnode, seqtype, field.type(), field.seq(seqtype));
 
 						// write out non-analog changes
 						if (!field.is_analog())
diff --git a/src/emu/ioport.h b/src/emu/ioport.h
index 2f26626..a9a4d49 100644
--- a/src/emu/ioport.h
+++ b/src/emu/ioport.h
@@ -654,6 +654,7 @@ enum
 //**************************************************************************
 
 // forward declarations
+namespace util { namespace xml { class data_node; } }
 class ioport_list;
 class ioport_port;
 struct ioport_port_live;
@@ -661,7 +662,6 @@ class ioport_field;
 struct ioport_field_live;
 class ioport_manager;
 class natural_keyboard;
-class xml_data_node;
 class analog_field;
 
 // constructor function pointer
@@ -1436,16 +1436,16 @@ private:
 	input_seq_type token_to_seq_type(const char *string);
 	static const char *const seqtypestrings[];
 
-	void load_config(config_type cfg_type, xml_data_node *parentnode);
-	void load_remap_table(xml_data_node const *parentnode);
-	bool load_default_config(xml_data_node const *portnode, int type, int player, const input_seq *newseq);
-	bool load_game_config(xml_data_node const *portnode, int type, int player, const input_seq *newseq);
+	void load_config(config_type cfg_type, util::xml::data_node const *parentnode);
+	void load_remap_table(util::xml::data_node const *parentnode);
+	bool load_default_config(util::xml::data_node const *portnode, int type, int player, const input_seq *newseq);
+	bool load_game_config(util::xml::data_node const *portnode, int type, int player, const input_seq *newseq);
 
-	void save_config(config_type cfg_type, xml_data_node *parentnode);
-	void save_sequence(xml_data_node *parentnode, input_seq_type type, ioport_type porttype, const input_seq &seq);
+	void save_config(config_type cfg_type, util::xml::data_node *parentnode);
+	void save_sequence(util::xml::data_node &parentnode, input_seq_type type, ioport_type porttype, const input_seq &seq);
 	bool save_this_input_field_type(ioport_type type);
-	void save_default_inputs(xml_data_node *parentnode);
-	void save_game_inputs(xml_data_node *parentnode);
+	void save_default_inputs(util::xml::data_node &parentnode);
+	void save_game_inputs(util::xml::data_node &parentnode);
 
 	template<typename _Type> _Type playback_read(_Type &result);
 	time_t playback_init();
diff --git a/src/emu/main.h b/src/emu/main.h
index 7b753dd..12f0f1a 100644
--- a/src/emu/main.h
+++ b/src/emu/main.h
@@ -59,7 +59,7 @@ public:
 	static void draw_user_interface(running_machine& machine);
 	static void periodic_check();
 	static bool frame_hook();
-	static void layout_file_cb(xml_data_node &layout);
+	static void layout_file_cb(util::xml::data_node &layout);
 	static bool standalone();
 };
 
diff --git a/src/emu/network.cpp b/src/emu/network.cpp
index 8239949..259cca3 100644
--- a/src/emu/network.cpp
+++ b/src/emu/network.cpp
@@ -24,7 +24,7 @@
 network_manager::network_manager(running_machine &machine)
 	: m_machine(machine)
 {
-	machine.configuration().config_register("network", config_saveload_delegate(&network_manager::config_load, this), config_saveload_delegate(&network_manager::config_save, this));
+	machine.configuration().config_register("network", config_load_delegate(&network_manager::config_load, this), config_save_delegate(&network_manager::config_save, this));
 }
 
 //-------------------------------------------------
@@ -32,12 +32,11 @@ network_manager::network_manager(running_machine &machine)
 //  configuration file
 //-------------------------------------------------
 
-void network_manager::config_load(config_type cfg_type, xml_data_node *parentnode)
+void network_manager::config_load(config_type cfg_type, util::xml::data_node const *parentnode)
 {
-	xml_data_node const *node;
-	if ((cfg_type == config_type::CONFIG_TYPE_GAME) && (parentnode != nullptr))
+	if ((cfg_type == config_type::GAME) && (parentnode != nullptr))
 	{
-		for (node = parentnode->get_child("device"); node; node = node->get_next_sibling("device"))
+		for (util::xml::data_node const *node = parentnode->get_child("device"); node; node = node->get_next_sibling("device"))
 		{
 			const char *tag = node->get_attribute_string("tag", nullptr);
 
@@ -68,16 +67,14 @@ void network_manager::config_load(config_type cfg_type, xml_data_node *parentnod
 //  file
 //-------------------------------------------------
 
-void network_manager::config_save(config_type cfg_type, xml_data_node *parentnode)
+void network_manager::config_save(config_type cfg_type, util::xml::data_node *parentnode)
 {
-	xml_data_node *node;
-
 	/* only care about game-specific data */
-	if (cfg_type == config_type::CONFIG_TYPE_GAME)
+	if (cfg_type == config_type::GAME)
 	{
 		for (device_network_interface &network : network_interface_iterator(machine().root_device()))
 		{
-			node = parentnode->add_child("device", nullptr);
+			util::xml::data_node *const node = parentnode->add_child("device", nullptr);
 			if (node != nullptr)
 			{
 				node->set_attribute("tag", network.device().tag());
diff --git a/src/emu/network.h b/src/emu/network.h
index 41ed328..29cf8c3 100644
--- a/src/emu/network.h
+++ b/src/emu/network.h
@@ -9,8 +9,8 @@
 
 #pragma once
 
-#ifndef __NETWORK_H__
-#define __NETWORK_H__
+#ifndef MAME_EMU_NETWORK_H
+#define MAME_EMU_NETWORK_H
 
 // ======================> network_manager
 
@@ -23,11 +23,11 @@ public:
 	// getters
 	running_machine &machine() const { return m_machine; }
 private:
-	void config_load(config_type cfg_type, xml_data_node *parentnode);
-	void config_save(config_type cfg_type, xml_data_node *parentnode);
+	void config_load(config_type cfg_type, util::xml::data_node const *parentnode);
+	void config_save(config_type cfg_type, util::xml::data_node *parentnode);
 
 	// internal state
 	running_machine &   m_machine;                  // reference to our machine
 };
 
-#endif /* __NETWORK_H__ */
+#endif /* MAME_EMU_NETWORK_H */
diff --git a/src/emu/render.cpp b/src/emu/render.cpp
index d1ee1a6..f1e7a95 100644
--- a/src/emu/render.cpp
+++ b/src/emu/render.cpp
@@ -1701,9 +1701,9 @@ bool render_target::load_layout_file(const char *dirname, const internal_layout
 bool render_target::load_layout_file(const char *dirname, const char *filename)
 {
 	// if the first character of the "file" is an open brace, assume it is an XML string
-	xml_data_node *rootnode;
+	util::xml::data_node *rootnode;
 	if (filename[0] == '<')
-		rootnode = xml_data_node::string_read(filename, nullptr);
+		rootnode = util::xml::data_node::string_read(filename, nullptr);
 
 	// otherwise, assume it is a file
 	else
@@ -1720,7 +1720,7 @@ bool render_target::load_layout_file(const char *dirname, const char *filename)
 			return false;
 
 		// read the file
-		rootnode = xml_data_node::file_read(layoutfile, nullptr);
+		rootnode = util::xml::data_node::file_read(layoutfile, nullptr);
 	}
 
 	// if we didn't get a properly-formatted XML file, record a warning and exit
@@ -2215,7 +2215,7 @@ int render_target::view_index(layout_view &targetview) const
 //  config_load - process config information
 //-------------------------------------------------
 
-void render_target::config_load(xml_data_node const &targetnode)
+void render_target::config_load(util::xml::data_node const &targetnode)
 {
 	// find the view
 	const char *viewname = targetnode.get_attribute_string("view", nullptr);
@@ -2290,7 +2290,7 @@ void render_target::config_load(xml_data_node const &targetnode)
 //  return false if we are the same as the default
 //-------------------------------------------------
 
-bool render_target::config_save(xml_data_node &targetnode)
+bool render_target::config_save(util::xml::data_node &targetnode)
 {
 	bool changed = false;
 
@@ -2618,7 +2618,7 @@ render_manager::render_manager(running_machine &machine)
 		m_ui_container(global_alloc(render_container(*this)))
 {
 	// register callbacks
-	machine.configuration().config_register("video", config_saveload_delegate(&render_manager::config_load, this), config_saveload_delegate(&render_manager::config_save, this));
+	machine.configuration().config_register("video", config_load_delegate(&render_manager::config_load, this), config_save_delegate(&render_manager::config_save, this));
 
 	// create one container per screen
 	for (screen_device &screen : screen_device_iterator(machine.root_device()))
@@ -2870,10 +2870,10 @@ void render_manager::container_free(render_container *container)
 //  configuration file
 //-------------------------------------------------
 
-void render_manager::config_load(config_type cfg_type, xml_data_node *parentnode)
+void render_manager::config_load(config_type cfg_type, util::xml::data_node const *parentnode)
 {
 	// we only care about game files
-	if (cfg_type != config_type::CONFIG_TYPE_GAME)
+	if (cfg_type != config_type::GAME)
 		return;
 
 	// might not have any data
@@ -2881,7 +2881,7 @@ void render_manager::config_load(config_type cfg_type, xml_data_node *parentnode
 		return;
 
 	// check the UI target
-	xml_data_node const *const uinode = parentnode->get_child("interface");
+	util::xml::data_node const *const uinode = parentnode->get_child("interface");
 	if (uinode != nullptr)
 	{
 		render_target *target = target_by_index(uinode->get_attribute_int("target", 0));
@@ -2890,7 +2890,7 @@ void render_manager::config_load(config_type cfg_type, xml_data_node *parentnode
 	}
 
 	// iterate over target nodes
-	for (xml_data_node const *targetnode = parentnode->get_child("target"); targetnode; targetnode = targetnode->get_next_sibling("target"))
+	for (util::xml::data_node const *targetnode = parentnode->get_child("target"); targetnode; targetnode = targetnode->get_next_sibling("target"))
 	{
 		render_target *target = target_by_index(targetnode->get_attribute_int("index", -1));
 		if (target != nullptr)
@@ -2898,7 +2898,7 @@ void render_manager::config_load(config_type cfg_type, xml_data_node *parentnode
 	}
 
 	// iterate over screen nodes
-	for (xml_data_node const *screennode = parentnode->get_child("screen"); screennode; screennode = screennode->get_next_sibling("screen"))
+	for (util::xml::data_node const *screennode = parentnode->get_child("screen"); screennode; screennode = screennode->get_next_sibling("screen"))
 	{
 		int index = screennode->get_attribute_int("index", -1);
 		render_container *container = m_screen_container_list.find(index);
@@ -2929,17 +2929,17 @@ void render_manager::config_load(config_type cfg_type, xml_data_node *parentnode
 //  file
 //-------------------------------------------------
 
-void render_manager::config_save(config_type cfg_type, xml_data_node *parentnode)
+void render_manager::config_save(config_type cfg_type, util::xml::data_node *parentnode)
 {
 	// we only care about game files
-	if (cfg_type != config_type::CONFIG_TYPE_GAME)
+	if (cfg_type != config_type::GAME)
 		return;
 
 	// write out the interface target
 	if (m_ui_target->index() != 0)
 	{
 		// create a node for it
-		xml_data_node *const uinode = parentnode->add_child("interface", nullptr);
+		util::xml::data_node *const uinode = parentnode->add_child("interface", nullptr);
 		if (uinode != nullptr)
 			uinode->set_attribute_int("target", m_ui_target->index());
 	}
@@ -2953,7 +2953,7 @@ void render_manager::config_save(config_type cfg_type, xml_data_node *parentnode
 			break;
 
 		// create a node
-		xml_data_node *const targetnode = parentnode->add_child("target", nullptr);
+		util::xml::data_node *const targetnode = parentnode->add_child("target", nullptr);
 		if (targetnode != nullptr && !target->config_save(*targetnode))
 			targetnode->delete_node();
 	}
@@ -2963,7 +2963,7 @@ void render_manager::config_save(config_type cfg_type, xml_data_node *parentnode
 	for (render_container *container = m_screen_container_list.first(); container != nullptr; container = container->next(), scrnum++)
 	{
 		// create a node
-		xml_data_node *const screennode = parentnode->add_child("screen", nullptr);
+		util::xml::data_node *const screennode = parentnode->add_child("screen", nullptr);
 		if (screennode != nullptr)
 		{
 			bool changed = false;
diff --git a/src/emu/render.h b/src/emu/render.h
index edffd76..34f5734 100644
--- a/src/emu/render.h
+++ b/src/emu/render.h
@@ -163,11 +163,11 @@ constexpr u32 PRIMFLAG_PACKABLE = 1 << PRIMFLAG_PACKABLE_SHIFT;
 //**************************************************************************
 
 // forward definitions
+namespace util { namespace xml { class data_node; } }
 class device_t;
 class screen_device;
 class render_container;
 class render_manager;
-class xml_data_node;
 class render_font;
 struct object_transform;
 class layout_element;
@@ -645,7 +645,7 @@ class layout_element
 
 public:
 	// construction/destruction
-	layout_element(running_machine &machine, xml_data_node const &elemnode, const char *dirname);
+	layout_element(running_machine &machine, util::xml::data_node const &elemnode, const char *dirname);
 	virtual ~layout_element();
 
 	// getters
@@ -664,7 +664,7 @@ private:
 		typedef std::unique_ptr<component> ptr;
 
 		// construction/destruction
-		component(running_machine &machine, xml_data_node const &compnode, const char *dirname);
+		component(running_machine &machine, util::xml::data_node const &compnode, const char *dirname);
 		virtual ~component() = default;
 
 		// setup
@@ -704,7 +704,7 @@ private:
 	{
 	public:
 		// construction/destruction
-		image_component(running_machine &machine, xml_data_node const &compnode, const char *dirname);
+		image_component(running_machine &machine, util::xml::data_node const &compnode, const char *dirname);
 
 	protected:
 		// overrides
@@ -728,7 +728,7 @@ private:
 	{
 	public:
 		// construction/destruction
-		rect_component(running_machine &machine, xml_data_node const &compnode, const char *dirname);
+		rect_component(running_machine &machine, util::xml::data_node const &compnode, const char *dirname);
 
 	protected:
 		// overrides
@@ -740,7 +740,7 @@ private:
 	{
 	public:
 		// construction/destruction
-		disk_component(running_machine &machine, xml_data_node const &compnode, const char *dirname);
+		disk_component(running_machine &machine, util::xml::data_node const &compnode, const char *dirname);
 
 	protected:
 		// overrides
@@ -752,7 +752,7 @@ private:
 	{
 	public:
 		// construction/destruction
-		text_component(running_machine &machine, xml_data_node const &compnode, const char *dirname);
+		text_component(running_machine &machine, util::xml::data_node const &compnode, const char *dirname);
 
 	protected:
 		// overrides
@@ -769,7 +769,7 @@ private:
 	{
 	public:
 		// construction/destruction
-		led7seg_component(running_machine &machine, xml_data_node const &compnode, const char *dirname);
+		led7seg_component(running_machine &machine, util::xml::data_node const &compnode, const char *dirname);
 
 	protected:
 		// overrides
@@ -782,7 +782,7 @@ private:
 	{
 	public:
 		// construction/destruction
-		led8seg_gts1_component(running_machine &machine, xml_data_node const &compnode, const char *dirname);
+		led8seg_gts1_component(running_machine &machine, util::xml::data_node const &compnode, const char *dirname);
 
 	protected:
 		// overrides
@@ -795,7 +795,7 @@ private:
 	{
 	public:
 		// construction/destruction
-		led14seg_component(running_machine &machine, xml_data_node const &compnode, const char *dirname);
+		led14seg_component(running_machine &machine, util::xml::data_node const &compnode, const char *dirname);
 
 	protected:
 		// overrides
@@ -808,7 +808,7 @@ private:
 	{
 	public:
 		// construction/destruction
-		led16seg_component(running_machine &machine, xml_data_node const &compnode, const char *dirname);
+		led16seg_component(running_machine &machine, util::xml::data_node const &compnode, const char *dirname);
 
 	protected:
 		// overrides
@@ -821,7 +821,7 @@ private:
 	{
 	public:
 		// construction/destruction
-		led14segsc_component(running_machine &machine, xml_data_node const &compnode, const char *dirname);
+		led14segsc_component(running_machine &machine, util::xml::data_node const &compnode, const char *dirname);
 
 	protected:
 		// overrides
@@ -834,7 +834,7 @@ private:
 	{
 	public:
 		// construction/destruction
-		led16segsc_component(running_machine &machine, xml_data_node const &compnode, const char *dirname);
+		led16segsc_component(running_machine &machine, util::xml::data_node const &compnode, const char *dirname);
 
 	protected:
 		// overrides
@@ -847,7 +847,7 @@ private:
 	{
 	public:
 		// construction/destruction
-		dotmatrix_component(int dots, running_machine &machine, xml_data_node const &compnode, const char *dirname);
+		dotmatrix_component(int dots, running_machine &machine, util::xml::data_node const &compnode, const char *dirname);
 
 	protected:
 		// overrides
@@ -864,7 +864,7 @@ private:
 	{
 	public:
 		// construction/destruction
-		simplecounter_component(running_machine &machine, xml_data_node const &compnode, const char *dirname);
+		simplecounter_component(running_machine &machine, util::xml::data_node const &compnode, const char *dirname);
 
 	protected:
 		// overrides
@@ -885,7 +885,7 @@ private:
 
 	public:
 		// construction/destruction
-		reel_component(running_machine &machine, xml_data_node const &compnode, const char *dirname);
+		reel_component(running_machine &machine, util::xml::data_node const &compnode, const char *dirname);
 
 	protected:
 		// overrides
@@ -932,13 +932,13 @@ private:
 		int                 m_state;        // associated state number
 	};
 
-	typedef component::ptr (*make_component_func)(running_machine &machine, xml_data_node const &compnode, const char *dirname);
+	typedef component::ptr (*make_component_func)(running_machine &machine, util::xml::data_node const &compnode, const char *dirname);
 	typedef std::map<std::string, make_component_func> make_component_map;
 
 	// internal helpers
 	static void element_scale(bitmap_argb32 &dest, bitmap_argb32 &source, const rectangle &sbounds, void *param);
-	template <typename T> static component::ptr make_component(running_machine &machine, xml_data_node const &compnode, const char *dirname);
-	template <int D> static component::ptr make_dotmatrix_component(running_machine &machine, xml_data_node const &compnode, const char *dirname);
+	template <typename T> static component::ptr make_component(running_machine &machine, util::xml::data_node const &compnode, const char *dirname);
+	template <int D> static component::ptr make_dotmatrix_component(running_machine &machine, util::xml::data_node const &compnode, const char *dirname);
 
 	static make_component_map const s_make_component; // maps component XML names to creator functions
 
@@ -969,7 +969,7 @@ public:
 
 	public:
 		// construction/destruction
-		item(running_machine &machine, xml_data_node const &itemnode, simple_list<layout_element> &elemlist);
+		item(running_machine &machine, util::xml::data_node const &itemnode, simple_list<layout_element> &elemlist);
 		virtual ~item();
 
 		// getters
@@ -1005,7 +1005,7 @@ public:
 	};
 
 	// construction/destruction
-	layout_view(running_machine &machine, xml_data_node const &viewnode, simple_list<layout_element> &elemlist);
+	layout_view(running_machine &machine, util::xml::data_node const &viewnode, simple_list<layout_element> &elemlist);
 	virtual ~layout_view();
 
 	// getters
@@ -1058,7 +1058,7 @@ class layout_file
 
 public:
 	// construction/destruction
-	layout_file(running_machine &machine, xml_data_node const &rootnode, const char *dirname);
+	layout_file(running_machine &machine, util::xml::data_node const &rootnode, const char *dirname);
 	virtual ~layout_file();
 
 	// getters
@@ -1171,8 +1171,8 @@ private:
 	bool map_point_internal(s32 target_x, s32 target_y, render_container *container, float &mapped_x, float &mapped_y, ioport_port *&mapped_input_port, ioport_value &mapped_input_mask);
 
 	// config callbacks
-	void config_load(xml_data_node const &targetnode);
-	bool config_save(xml_data_node &targetnode);
+	void config_load(util::xml::data_node const &targetnode);
+	bool config_save(util::xml::data_node &targetnode);
 
 	// view lookups
 	layout_view *view_by_index(int index) const;
@@ -1277,8 +1277,8 @@ private:
 	void container_free(render_container *container);
 
 	// config callbacks
-	void config_load(config_type cfg_type, xml_data_node *parentnode);
-	void config_save(config_type cfg_type, xml_data_node *parentnode);
+	void config_load(config_type cfg_type, util::xml::data_node const *parentnode);
+	void config_save(config_type cfg_type, util::xml::data_node *parentnode);
 
 	// internal state
 	running_machine &               m_machine;          // reference back to the machine
diff --git a/src/emu/rendfont.cpp b/src/emu/rendfont.cpp
index 9adbbe2..5e7f032 100644
--- a/src/emu/rendfont.cpp
+++ b/src/emu/rendfont.cpp
@@ -1,5 +1,5 @@
 // license:BSD-3-Clause
-// copyright-holders:Aaron Giles
+// copyright-holders:Aaron Giles, Vas Crabb
 /***************************************************************************
 
     rendfont.c
@@ -16,10 +16,432 @@
 #include "osdepend.h"
 #include "uismall.fh"
 
-#include "ui/cmdrender.h"
+#include "ui/uicmd14.fh"
+#include "ui/cmddata.h"
 
+#include <algorithm>
 #include <cstddef>
 #include <cstring>
+#include <iterator>
+#include <limits>
+
+
+#define VERBOSE 0
+
+#define LOG(...) do { if (VERBOSE) osd_printf_verbose(__VA_ARGS__); } while (0)
+
+
+namespace {
+
+template <typename Iterator>
+class bdf_helper
+{
+public:
+	bdf_helper(Iterator const &begin, Iterator const &end)
+		: m_keyword_begin(begin)
+		, m_keyword_end(begin)
+		, m_value_begin(begin)
+		, m_value_end(begin)
+		, m_line_end(begin)
+		, m_end(end)
+	{
+		next_line();
+	}
+
+	bool at_end() const { return m_end == m_keyword_begin; }
+
+	void next_line()
+	{
+		m_keyword_begin = m_line_end;
+		while ((m_end != m_keyword_begin) && (('\r' == *m_keyword_begin) || ('\n' == *m_keyword_begin)))
+			++m_keyword_begin;
+
+		m_keyword_end = m_keyword_begin;
+		while ((m_end != m_keyword_end) && (' ' != *m_keyword_end) && ('\t' != *m_keyword_end) && ('\r' != *m_keyword_end) && ('\n' != *m_keyword_end))
+			++m_keyword_end;
+
+		m_value_begin = m_keyword_end;
+		while ((m_end != m_value_begin) && ((' ' == *m_value_begin) || ('\t' == *m_value_begin)) && ('\r' != *m_value_begin) && ('\n' != *m_value_begin))
+			++m_value_begin;
+
+		m_value_end = m_line_end = m_value_begin;
+		while ((m_end != m_line_end) && ('\r' != *m_line_end) && ('\n' != *m_line_end))
+		{
+			if ((' ' != *m_line_end) && ('\t' != *m_line_end))
+				m_value_end = ++m_line_end;
+			else
+				++m_line_end;
+		}
+	}
+
+	bool is_keyword(char const *keyword) const
+	{
+		Iterator pos(m_keyword_begin);
+		while (true)
+		{
+			if (m_keyword_end == pos)
+			{
+				return '\0' == *keyword;
+			}
+			else if (('\0' == *keyword) || (*pos != *keyword))
+			{
+				return false;
+			}
+			else
+			{
+				++pos;
+				++keyword;
+			}
+		}
+	}
+
+	Iterator const &keyword_begin() const { return m_keyword_begin; }
+	Iterator const &keyword_end() const { return m_keyword_end; }
+	auto keyword_length() const { return std::distance(m_keyword_begin, m_keyword_end); }
+
+	Iterator const &value_begin() const { return m_value_begin; }
+	Iterator const &value_end() const { return m_value_end; }
+	auto value_length() const { return std::distance(m_value_begin, m_value_end); }
+
+private:
+	Iterator        m_keyword_begin;
+	Iterator        m_keyword_end;
+	Iterator        m_value_begin;
+	Iterator        m_value_end;
+	Iterator        m_line_end;
+	Iterator const  m_end;
+};
+
+
+class bdc_header
+{
+public:
+	static constexpr unsigned MAJVERSION = 1;
+	static constexpr unsigned MINVERSION = 0;
+
+	bool read(emu_file &f)
+	{
+		return f.read(m_data, sizeof(m_data)) == sizeof(m_data);
+	}
+	bool write(emu_file &f)
+	{
+		return f.write(m_data, sizeof(m_data)) == sizeof(m_data);
+	}
+
+	bool check_magic() const
+	{
+		return !std::memcmp(MAGIC, m_data + OFFS_MAGIC, OFFS_MAJVERSION - OFFS_MAGIC);
+	}
+	unsigned get_major_version() const
+	{
+		return m_data[OFFS_MAJVERSION];
+	}
+	unsigned get_minor_version() const
+	{
+		return m_data[OFFS_MINVERSION];
+	}
+	u64 get_original_length() const
+	{
+		return
+				(u64(m_data[OFFS_ORIGLENGTH + 0]) << (7 * 8)) |
+				(u64(m_data[OFFS_ORIGLENGTH + 1]) << (6 * 8)) |
+				(u64(m_data[OFFS_ORIGLENGTH + 2]) << (5 * 8)) |
+				(u64(m_data[OFFS_ORIGLENGTH + 3]) << (4 * 8)) |
+				(u64(m_data[OFFS_ORIGLENGTH + 4]) << (3 * 8)) |
+				(u64(m_data[OFFS_ORIGLENGTH + 5]) << (2 * 8)) |
+				(u64(m_data[OFFS_ORIGLENGTH + 6]) << (1 * 8)) |
+				(u64(m_data[OFFS_ORIGLENGTH + 7]) << (0 * 8));
+	}
+	u32 get_original_hash() const
+	{
+		return
+				(u32(m_data[OFFS_ORIGHASH + 0]) << (3 * 8)) |
+				(u32(m_data[OFFS_ORIGHASH + 1]) << (2 * 8)) |
+				(u32(m_data[OFFS_ORIGHASH + 2]) << (1 * 8)) |
+				(u32(m_data[OFFS_ORIGHASH + 3]) << (0 * 8));
+	}
+	u32 get_glyph_count() const
+	{
+		return
+				(u32(m_data[OFFS_GLYPHCOUNT + 0]) << (3 * 8)) |
+				(u32(m_data[OFFS_GLYPHCOUNT + 1]) << (2 * 8)) |
+				(u32(m_data[OFFS_GLYPHCOUNT + 2]) << (1 * 8)) |
+				(u32(m_data[OFFS_GLYPHCOUNT + 3]) << (0 * 8));
+	}
+	u16 get_height() const
+	{
+		return
+				(u16(m_data[OFFS_HEIGHT + 0]) << (1 * 8)) |
+				(u16(m_data[OFFS_HEIGHT + 1]) << (0 * 8));
+	}
+	s16 get_y_offset() const
+	{
+		return
+				(u16(m_data[OFFS_YOFFSET + 0]) << (1 * 8)) |
+				(u16(m_data[OFFS_YOFFSET + 1]) << (0 * 8));
+	}
+	s32 get_default_character() const
+	{
+		return
+				(u32(m_data[OFFS_DEFCHAR + 0]) << (3 * 8)) |
+				(u32(m_data[OFFS_DEFCHAR + 1]) << (2 * 8)) |
+				(u32(m_data[OFFS_DEFCHAR + 2]) << (1 * 8)) |
+				(u32(m_data[OFFS_DEFCHAR + 3]) << (0 * 8));
+	}
+
+	void set_magic()
+	{
+		std::memcpy(m_data + OFFS_MAGIC, MAGIC, OFFS_MAJVERSION - OFFS_MAGIC);
+	}
+	void set_version()
+	{
+		m_data[OFFS_MAJVERSION] = MAJVERSION;
+		m_data[OFFS_MINVERSION] = MINVERSION;
+	}
+	void set_original_length(u64 value)
+	{
+		m_data[OFFS_ORIGLENGTH + 0] = u8((value >> (7 * 8)) & 0x00ff);
+		m_data[OFFS_ORIGLENGTH + 1] = u8((value >> (6 * 8)) & 0x00ff);
+		m_data[OFFS_ORIGLENGTH + 2] = u8((value >> (5 * 8)) & 0x00ff);
+		m_data[OFFS_ORIGLENGTH + 3] = u8((value >> (4 * 8)) & 0x00ff);
+		m_data[OFFS_ORIGLENGTH + 4] = u8((value >> (3 * 8)) & 0x00ff);
+		m_data[OFFS_ORIGLENGTH + 5] = u8((value >> (2 * 8)) & 0x00ff);
+		m_data[OFFS_ORIGLENGTH + 6] = u8((value >> (1 * 8)) & 0x00ff);
+		m_data[OFFS_ORIGLENGTH + 7] = u8((value >> (0 * 8)) & 0x00ff);
+	}
+	void set_original_hash(u32 value)
+	{
+		m_data[OFFS_ORIGHASH + 0] = u8((value >> (3 * 8)) & 0x00ff);
+		m_data[OFFS_ORIGHASH + 1] = u8((value >> (2 * 8)) & 0x00ff);
+		m_data[OFFS_ORIGHASH + 2] = u8((value >> (1 * 8)) & 0x00ff);
+		m_data[OFFS_ORIGHASH + 3] = u8((value >> (0 * 8)) & 0x00ff);
+	}
+	void set_glyph_count(u32 value)
+	{
+		m_data[OFFS_GLYPHCOUNT + 0] = u8((value >> (3 * 8)) & 0x00ff);
+		m_data[OFFS_GLYPHCOUNT + 1] = u8((value >> (2 * 8)) & 0x00ff);
+		m_data[OFFS_GLYPHCOUNT + 2] = u8((value >> (1 * 8)) & 0x00ff);
+		m_data[OFFS_GLYPHCOUNT + 3] = u8((value >> (0 * 8)) & 0x00ff);
+	}
+	void set_height(u16 value)
+	{
+		m_data[OFFS_HEIGHT + 0] = u8((value >> (1 * 8)) & 0x00ff);
+		m_data[OFFS_HEIGHT + 1] = u8((value >> (0 * 8)) & 0x00ff);
+	}
+	void set_y_offset(s16 value)
+	{
+		m_data[OFFS_YOFFSET + 0] = u8((value >> (1 * 8)) & 0x00ff);
+		m_data[OFFS_YOFFSET + 1] = u8((value >> (0 * 8)) & 0x00ff);
+	}
+	void set_default_character(s32 value)
+	{
+		m_data[OFFS_DEFCHAR + 0] = u8((value >> (3 * 8)) & 0x00ff);
+		m_data[OFFS_DEFCHAR + 1] = u8((value >> (2 * 8)) & 0x00ff);
+		m_data[OFFS_DEFCHAR + 2] = u8((value >> (1 * 8)) & 0x00ff);
+		m_data[OFFS_DEFCHAR + 3] = u8((value >> (0 * 8)) & 0x00ff);
+	}
+
+private:
+	static constexpr std::size_t    OFFS_MAGIC      = 0x00; // 0x06 bytes
+	static constexpr std::size_t    OFFS_MAJVERSION = 0x06; // 0x01 bytes (binary integer)
+	static constexpr std::size_t    OFFS_MINVERSION = 0x07; // 0x01 bytes (binary integer)
+	static constexpr std::size_t    OFFS_ORIGLENGTH = 0x08; // 0x08 bytes (big-endian binary integer)
+	static constexpr std::size_t    OFFS_ORIGHASH   = 0x10; // 0x04 bytes
+	static constexpr std::size_t    OFFS_GLYPHCOUNT = 0x14; // 0x04 bytes (big-endian binary integer)
+	static constexpr std::size_t    OFFS_HEIGHT     = 0x18; // 0x02 bytes (big-endian binary integer)
+	static constexpr std::size_t    OFFS_YOFFSET    = 0x1a; // 0x02 bytes (big-endian binary integer)
+	static constexpr std::size_t    OFFS_DEFCHAR    = 0x1c; // 0x04 bytes (big-endian binary integer)
+	static constexpr std::size_t    OFFS_END        = 0x20;
+
+	static u8 const                 MAGIC[OFFS_MAJVERSION - OFFS_MAGIC];
+
+	u8                              m_data[OFFS_END];
+};
+
+u8 const bdc_header::MAGIC[OFFS_MAJVERSION - OFFS_MAGIC] = { 'b', 'd', 'c', 'f', 'n', 't' };
+
+
+class bdc_table_entry
+{
+public:
+	bdc_table_entry(void *bytes)
+		: m_ptr(reinterpret_cast<u8 *>(bytes))
+	{
+	}
+	bdc_table_entry(bdc_table_entry const &that) = default;
+	bdc_table_entry(bdc_table_entry &&that) = default;
+
+	bdc_table_entry get_next() const
+	{
+		return bdc_table_entry(m_ptr + OFFS_END);
+	}
+
+	u32 get_encoding() const
+	{
+		return
+				(u32(m_ptr[OFFS_ENCODING + 0]) << (3 * 8)) |
+				(u32(m_ptr[OFFS_ENCODING + 1]) << (2 * 8)) |
+				(u32(m_ptr[OFFS_ENCODING + 2]) << (1 * 8)) |
+				(u32(m_ptr[OFFS_ENCODING + 3]) << (0 * 8));
+	}
+	u16 get_x_advance() const
+	{
+		return
+				(u16(m_ptr[OFFS_XADVANCE + 0]) << (1 * 8)) |
+				(u16(m_ptr[OFFS_XADVANCE + 1]) << (0 * 8));
+	}
+	s16 get_bb_x_offset() const
+	{
+		return
+				(u16(m_ptr[OFFS_BBXOFFSET + 0]) << (1 * 8)) |
+				(u16(m_ptr[OFFS_BBXOFFSET + 1]) << (0 * 8));
+	}
+	s16 get_bb_y_offset() const
+	{
+		return
+				(u16(m_ptr[OFFS_BBYOFFSET + 0]) << (1 * 8)) |
+				(u16(m_ptr[OFFS_BBYOFFSET + 1]) << (0 * 8));
+	}
+	u16 get_bb_width() const
+	{
+		return
+				(u16(m_ptr[OFFS_BBWIDTH + 0]) << (1 * 8)) |
+				(u16(m_ptr[OFFS_BBWIDTH + 1]) << (0 * 8));
+	}
+	u16 get_bb_height() const
+	{
+		return
+				(u16(m_ptr[OFFS_BBHEIGHT + 0]) << (1 * 8)) |
+				(u16(m_ptr[OFFS_BBHEIGHT + 1]) << (0 * 8));
+	}
+
+	void set_encoding(u32 value)
+	{
+		m_ptr[OFFS_ENCODING + 0] = u8((value >> (3 * 8)) & 0x00ff);
+		m_ptr[OFFS_ENCODING + 1] = u8((value >> (2 * 8)) & 0x00ff);
+		m_ptr[OFFS_ENCODING + 2] = u8((value >> (1 * 8)) & 0x00ff);
+		m_ptr[OFFS_ENCODING + 3] = u8((value >> (0 * 8)) & 0x00ff);
+	}
+	void set_x_advance(u16 value)
+	{
+		m_ptr[OFFS_XADVANCE + 0] = u8((value >> (1 * 8)) & 0x00ff);
+		m_ptr[OFFS_XADVANCE + 1] = u8((value >> (0 * 8)) & 0x00ff);
+	}
+	void set_bb_x_offset(s16 value)
+	{
+		m_ptr[OFFS_BBXOFFSET + 0] = u8((value >> (1 * 8)) & 0x00ff);
+		m_ptr[OFFS_BBXOFFSET + 1] = u8((value >> (0 * 8)) & 0x00ff);
+	}
+	void set_bb_y_offset(s16 value)
+	{
+		m_ptr[OFFS_BBYOFFSET + 0] = u8((value >> (1 * 8)) & 0x00ff);
+		m_ptr[OFFS_BBYOFFSET + 1] = u8((value >> (0 * 8)) & 0x00ff);
+	}
+	void set_bb_width(u16 value)
+	{
+		m_ptr[OFFS_BBWIDTH + 0] = u8((value >> (1 * 8)) & 0x00ff);
+		m_ptr[OFFS_BBWIDTH + 1] = u8((value >> (0 * 8)) & 0x00ff);
+	}
+	void set_bb_height(u16 value)
+	{
+		m_ptr[OFFS_BBHEIGHT + 0] = u8((value >> (1 * 8)) & 0x00ff);
+		m_ptr[OFFS_BBHEIGHT + 1] = u8((value >> (0 * 8)) & 0x00ff);
+	}
+
+	bdc_table_entry &operator=(bdc_table_entry const &that) = default;
+	bdc_table_entry &operator=(bdc_table_entry &&that) = default;
+
+	static std::size_t size()
+	{
+		return OFFS_END;
+	}
+
+private:
+	static constexpr std::size_t    OFFS_ENCODING   = 0x00; // 0x04 bytes (big-endian binary integer)
+	static constexpr std::size_t    OFFS_XADVANCE   = 0x04; // 0x02 bytes (big-endian binary integer)
+	// two bytes reserved
+	static constexpr std::size_t    OFFS_BBXOFFSET  = 0x08; // 0x02 bytes (big-endian binary integer)
+	static constexpr std::size_t    OFFS_BBYOFFSET  = 0x0a; // 0x02 bytes (big-endian binary integer)
+	static constexpr std::size_t    OFFS_BBWIDTH    = 0x0c; // 0x02 bytes (big-endian binary integer)
+	static constexpr std::size_t    OFFS_BBHEIGHT   = 0x0e; // 0x02 bytes (big-endian binary integer)
+	static constexpr std::size_t    OFFS_END        = 0x10;
+
+	u8                              *m_ptr;
+};
+
+} // anonymous namespace
+
+
+void convert_command_glyph(std::string &str)
+{
+	str.c_str(); // force NUL-termination - we depend on it later
+	std::size_t const len(str.length());
+	std::vector<char> buf(2 * (len + 1));
+	std::size_t j(0);
+	for (std::size_t i = 0; len > i; )
+	{
+		// decode UTF-8
+		char32_t uchar;
+		int const codelen(uchar_from_utf8(&uchar, &str[i], len - i));
+		if (0 >= codelen)
+			break;
+		i += codelen;
+
+		// check for three metacharacters
+		fix_command_t const *fixcmd(nullptr);
+		switch (uchar)
+		{
+		case COMMAND_CONVERT_TEXT:
+			for (fix_strings_t *fixtext = convert_text; fixtext->glyph_code; ++fixtext)
+			{
+				if (!fixtext->glyph_str_len)
+					fixtext->glyph_str_len = std::strlen(fixtext->glyph_str);
+
+				if (!std::strncmp(fixtext->glyph_str, &str[i], fixtext->glyph_str_len))
+				{
+					uchar = fixtext->glyph_code + COMMAND_UNICODE;
+					i += strlen(fixtext->glyph_str);
+					break;
+				}
+			}
+			break;
+
+		case COMMAND_DEFAULT_TEXT:
+			fixcmd = default_text;
+			break;
+
+		case COMMAND_EXPAND_TEXT:
+			fixcmd = expand_text;
+			break;
+		}
+
+		// this substitutes a single character
+		if (fixcmd)
+		{
+			if (str[i] == uchar)
+			{
+				++i;
+			}
+			else
+			{
+				while (fixcmd->glyph_code && (fixcmd->glyph_char != str[i]))
+					++fixcmd;
+				if (fixcmd->glyph_code)
+				{
+					uchar = COMMAND_UNICODE + fixcmd->glyph_code;
+					++i;
+				}
+			}
+		}
+
+		// copy character to output
+		int const outlen(utf8_from_uchar(&buf[j], buf.size() - j, uchar));
+		if (0 >= outlen)
+			break;
+		j += outlen;
+	}
+	str.assign(&buf[0], j);
+}
 
 
 const u64 render_font::CACHED_BDF_HASH_SIZE;
@@ -58,30 +480,36 @@ inline render_font::glyph &render_font::get_char(char32_t chnum)
 {
 	static glyph dummy_glyph;
 
-	// grab the table; if none, return the dummy character
-	if ((chnum / 256) >= ARRAY_LENGTH(m_glyphs))
-		return dummy_glyph;
-	if (!m_glyphs[chnum / 256] && m_format == FF_OSD)
-		m_glyphs[chnum / 256] = new glyph[256];
-	if (!m_glyphs[chnum / 256])
+	unsigned const page(chnum / 256);
+	if (page >= ARRAY_LENGTH(m_glyphs))
+	{
+		if ((0 <= m_defchar) && (chnum != m_defchar))
+			return get_char(m_defchar);
+		else
+			return dummy_glyph;
+	}
+	else if (!m_glyphs[page])
 	{
 		//mamep: make table for command glyph
-		if (chnum >= COMMAND_UNICODE && chnum < COMMAND_UNICODE + MAX_GLYPH_FONT)
-			m_glyphs[chnum / 256] = new glyph[256];
+		if ((m_format == format::OSD) || ((chnum >= COMMAND_UNICODE) && (chnum < COMMAND_UNICODE + MAX_GLYPH_FONT)))
+			m_glyphs[page] = new glyph[256];
+		else if ((0 <= m_defchar) && (chnum != m_defchar))
+			return get_char(m_defchar);
 		else
 			return dummy_glyph;
 	}
 
 	// if the character isn't generated yet, do it now
-	glyph &gl = m_glyphs[chnum / 256][chnum % 256];
+	glyph &gl = m_glyphs[page][chnum % 256];
 	if (!gl.bitmap.valid())
 	{
 		//mamep: command glyph support
 		if (m_height_cmd && chnum >= COMMAND_UNICODE && chnum < COMMAND_UNICODE + MAX_GLYPH_FONT)
 		{
-			glyph &glyph_ch = m_glyphs_cmd[chnum / 256][chnum % 256];
-			float scale = (float)m_height / (float)m_height_cmd;
-			if (m_format == FF_OSD) scale *= 0.90f;
+			glyph &glyph_ch = m_glyphs_cmd[page][chnum % 256];
+			float scale = float(m_height) / float(m_height_cmd);
+			if (m_format == format::OSD)
+				scale *= 0.90f;
 
 			if (!glyph_ch.bitmap.valid())
 				char_expand(chnum, glyph_ch);
@@ -89,11 +517,11 @@ inline render_font::glyph &render_font::get_char(char32_t chnum)
 			//mamep: for color glyph
 			gl.color = glyph_ch.color;
 
-			gl.width = (int)(glyph_ch.width * scale + 0.5f);
-			gl.xoffs = (int)(glyph_ch.xoffs * scale + 0.5f);
-			gl.yoffs = (int)(glyph_ch.yoffs * scale + 0.5f);
-			gl.bmwidth = (int)(glyph_ch.bmwidth * scale + 0.5f);
-			gl.bmheight = (int)(glyph_ch.bmheight * scale + 0.5f);
+			gl.width = int(glyph_ch.width * scale + 0.5f);
+			gl.xoffs = int(glyph_ch.xoffs * scale + 0.5f);
+			gl.yoffs = int(glyph_ch.yoffs * scale + 0.5f);
+			gl.bmwidth = int(glyph_ch.bmwidth * scale + 0.5f);
+			gl.bmheight = int(glyph_ch.bmheight * scale + 0.5f);
 
 			gl.bitmap.allocate(gl.bmwidth, gl.bmheight);
 			rectangle clip;
@@ -107,10 +535,11 @@ inline render_font::glyph &render_font::get_char(char32_t chnum)
 			gl.texture->set_bitmap(gl.bitmap, gl.bitmap.cliprect(), TEXFORMAT_ARGB32);
 		}
 		else
+		{
 			char_expand(chnum, gl);
+		}
 	}
 
-	// return the resulting character
 	return gl;
 }
 
@@ -125,55 +554,53 @@ inline render_font::glyph &render_font::get_char(char32_t chnum)
 //-------------------------------------------------
 
 render_font::render_font(render_manager &manager, const char *filename)
-	: m_manager(manager),
-		m_format(FF_UNKNOWN),
-		m_height(0),
-		m_yoffs(0),
-		m_scale(1.0f),
-		m_rawsize(0),
-		m_osdfont(),
-		m_height_cmd(0),
-		m_yoffs_cmd(0)
+	: m_manager(manager)
+	, m_format(format::UNKNOWN)
+	, m_height(0)
+	, m_yoffs(0)
+	, m_defchar(-1)
+	, m_scale(1.0f)
+	, m_rawsize(0)
+	, m_osdfont()
+	, m_height_cmd(0)
+	, m_yoffs_cmd(0)
 {
 	memset(m_glyphs, 0, sizeof(m_glyphs));
 	memset(m_glyphs_cmd, 0, sizeof(m_glyphs_cmd));
 
 	// if this is an OSD font, we're done
-	if (filename != nullptr)
+	if (filename)
 	{
 		m_osdfont = manager.machine().osd().font_alloc();
-		if (m_osdfont)
+		if (m_osdfont && m_osdfont->open(manager.machine().options().font_path(), filename, m_height))
 		{
-			if (m_osdfont->open(manager.machine().options().font_path(), filename, m_height))
-			{
-				m_scale = 1.0f / (float)m_height;
-				m_format = FF_OSD;
+			m_scale = 1.0f / float(m_height);
+			m_format = format::OSD;
 
-				//mamep: allocate command glyph font
-				render_font_command_glyph();
-				return;
-			}
-			m_osdfont.reset();
+			//mamep: allocate command glyph font
+			render_font_command_glyph();
+			return;
 		}
+		m_osdfont.reset();
 	}
 
 	// if the filename is 'default' default to 'ui.bdf' for backwards compatibility
-	if (filename != nullptr && core_stricmp(filename, "default") == 0)
+	if (filename && !core_stricmp(filename, "default"))
 		filename = "ui.bdf";
 
-	// attempt to load the cached version of the font first
-	if (filename != nullptr && load_cached_bdf(filename))
+	// attempt to load an external BDF font first
+	if (filename && load_cached_bdf(filename))
 	{
 		//mamep: allocate command glyph font
 		render_font_command_glyph();
 		return;
 	}
 
-	// load the raw data instead
+	// load the compiled in data instead
 	emu_file ramfile(OPEN_FLAG_READ);
-	osd_file::error filerr = ramfile.open_ram(font_uismall, sizeof(font_uismall));
-	if (filerr == osd_file::error::NONE)
-		load_cached(ramfile, 0);
+	osd_file::error const filerr(ramfile.open_ram(font_uismall, sizeof(font_uismall)));
+	if (osd_file::error::NONE == filerr)
+		load_cached(ramfile, 0, 0);
 	render_font_command_glyph();
 }
 
@@ -216,15 +643,15 @@ render_font::~render_font()
 
 void render_font::char_expand(char32_t chnum, glyph &gl)
 {
-	rgb_t color = rgb_t(0xff,0xff,0xff,0xff);
-	bool is_cmd = (chnum >= COMMAND_UNICODE && chnum < COMMAND_UNICODE + MAX_GLYPH_FONT);
+	LOG("render_font::char_expand: expanding character %u\n", unsigned(chnum));
 
-	if (gl.color)
-		color = gl.color;
+	rgb_t const fgcol(gl.color ? gl.color : rgb_t(0xff, 0xff, 0xff, 0xff));
+	rgb_t const bgcol(0x00, 0xff, 0xff, 0xff);
+	bool const is_cmd((chnum >= COMMAND_UNICODE) && (chnum < COMMAND_UNICODE + MAX_GLYPH_FONT));
 
 	if (is_cmd)
 	{
-		// punt if nothing there
+		// abort if nothing there
 		if (gl.bmwidth == 0 || gl.bmheight == 0 || gl.rawdata == nullptr)
 			return;
 
@@ -245,37 +672,47 @@ void render_font::char_expand(char32_t chnum, glyph &gl)
 					if (accumbit == 7)
 						accum = *ptr++;
 					if (dest != nullptr)
-						*dest++ = (accum & (1 << accumbit)) ? color : rgb_t(0x00,0xff,0xff,0xff);
+						*dest++ = (accum & (1 << accumbit)) ? fgcol : bgcol;
 					accumbit = (accumbit - 1) & 7;
 				}
 			}
 		}
 	}
-	// if we're an OSD font, query the info
-	else if (m_format == FF_OSD)
+	else if (m_format == format::OSD)
 	{
-		// we set bmwidth to -1 if we've previously queried and failed
-		if (gl.bmwidth == -1)
+		// if we're an OSD font, query the info
+		if (0 > gl.bmwidth)
+		{
+			// we set bmwidth to -1 if we've previously queried and failed
+			LOG("render_font::char_expand: previously failed to get bitmap from OSD font\n");
 			return;
-
-		// attempt to get the font bitmap; if we fail, set bmwidth to -1
+		}
 		if (!m_osdfont->get_bitmap(chnum, gl.bitmap, gl.width, gl.xoffs, gl.yoffs))
 		{
+			// attempt to get the font bitmap failed - set bmwidth to -1
+			LOG("render_font::char_expand: get bitmap from OSD font failed\n");
 			gl.bitmap.reset();
 			gl.bmwidth = -1;
 			return;
 		}
-
-		// populate the bmwidth/bmheight fields
-		gl.bmwidth = gl.bitmap.width();
-		gl.bmheight = gl.bitmap.height();
+		else
+		{
+			// populate the bmwidth/bmheight fields
+			LOG("render_font::char_expand: got %dx%d bitmap from OSD font\n", gl.bitmap.width(), gl.bitmap.height());
+			gl.bmwidth = gl.bitmap.width();
+			gl.bmheight = gl.bitmap.height();
+		}
+	}
+	else if (!gl.bmwidth || !gl.bmheight || !gl.rawdata)
+	{
+		// abort if nothing there
+		LOG("render_font::char_expand: empty bitmap bounds or no raw data\n");
+		return;
 	}
-	// other formats need to parse their data
 	else
 	{
-		// punt if nothing there
-		if (gl.bmwidth == 0 || gl.bmheight == 0 || gl.rawdata == nullptr)
-			return;
+		// other formats need to parse their data
+		LOG("render_font::char_expand: building bitmap from raw data\n");
 
 		// allocate a new bitmap of the size we need
 		gl.bitmap.allocate(gl.bmwidth, m_height);
@@ -283,55 +720,55 @@ void render_font::char_expand(char32_t chnum, glyph &gl)
 
 		// extract the data
 		const char *ptr = gl.rawdata;
-		u8 accum = 0, accumbit = 7;
-		for (int y = 0; y < gl.bmheight; y++)
+		u8 accum(0), accumbit(7);
+		for (int y = 0; y < gl.bmheight; ++y)
 		{
-			int desty = y + m_height + m_yoffs - gl.yoffs - gl.bmheight;
-			u32 *dest = (desty >= 0 && desty < m_height) ? &gl.bitmap.pix32(desty) : nullptr;
+			int const desty(y + m_height + m_yoffs - gl.yoffs - gl.bmheight);
+			u32 *dest(((0 <= desty) && (m_height > desty)) ? &gl.bitmap.pix32(desty) : nullptr);
 
-			// text format
-			if (m_format == FF_TEXT)
+			if (m_format == format::TEXT)
 			{
-				// loop over bytes
-				for (int x = 0; x < gl.bmwidth; x += 4)
+				if (dest)
 				{
-					// scan for the next hex digit
-					int bits = -1;
-					while (*ptr != 13 && bits == -1)
+					for (int x = 0; gl.bmwidth > x; )
 					{
-						if (*ptr >= '0' && *ptr <= '9')
-							bits = *ptr++ - '0';
-						else if (*ptr >= 'A' && *ptr <= 'F')
-							bits = *ptr++ - 'A' + 10;
-						else if (*ptr >= 'a' && *ptr <= 'f')
-							bits = *ptr++ - 'a' + 10;
-						else
-							ptr++;
-					}
+						// scan for the next hex digit
+						int bits = -1;
+						while (('\r' != *ptr) && ('\n' != *ptr) && (0 > bits))
+						{
+							if (*ptr >= '0' && *ptr <= '9')
+								bits = *ptr++ - '0';
+							else if (*ptr >= 'A' && *ptr <= 'F')
+								bits = *ptr++ - 'A' + 10;
+							else if (*ptr >= 'a' && *ptr <= 'f')
+								bits = *ptr++ - 'a' + 10;
+							else
+								ptr++;
+						}
 
-					// expand the four bits
-					if (dest != nullptr)
-					{
-						*dest++ = (bits & 8) ? color : rgb_t(0x00,0xff,0xff,0xff);
-						*dest++ = (bits & 4) ? color : rgb_t(0x00,0xff,0xff,0xff);
-						*dest++ = (bits & 2) ? color : rgb_t(0x00,0xff,0xff,0xff);
-						*dest++ = (bits & 1) ? color : rgb_t(0x00,0xff,0xff,0xff);
+						// expand the four bits
+						*dest++ = (bits & 8) ? fgcol : bgcol;
+						if (gl.bmwidth > ++x)
+							*dest++ = (bits & 4) ? fgcol : bgcol;
+						if (gl.bmwidth > ++x)
+							*dest++ = (bits & 2) ? fgcol : bgcol;
+						if (gl.bmwidth > ++x)
+							*dest++ = (bits & 1) ? fgcol : bgcol;
+						++x;
 					}
 				}
 
 				// advance to the next line
 				ptr = next_line(ptr);
 			}
-
-			// cached format
-			else if (m_format == FF_CACHED)
+			else if (m_format == format::CACHED)
 			{
 				for (int x = 0; x < gl.bmwidth; x++)
 				{
 					if (accumbit == 7)
 						accum = *ptr++;
 					if (dest != nullptr)
-						*dest++ = (accum & (1 << accumbit)) ? color : rgb_t(0x00,0xff,0xff,0xff);
+						*dest++ = (accum & (1 << accumbit)) ? fgcol : bgcol;
 					accumbit = (accumbit - 1) & 7;
 				}
 			}
@@ -479,27 +916,45 @@ float render_font::utf8string_width(float height, float aspect, const char *utf8
 
 bool render_font::load_cached_bdf(const char *filename)
 {
+	osd_file::error filerr;
+	u32 chunk;
+	u64 bytes;
+
 	// first try to open the BDF itself
 	emu_file file(m_manager.machine().options().font_path(), OPEN_FLAG_READ);
-	osd_file::error filerr = file.open(filename);
+	filerr = file.open(filename);
 	if (filerr != osd_file::error::NONE)
 		return false;
 
 	// determine the file size and allocate memory
-	m_rawsize = file.size();
-	m_rawdata.resize(m_rawsize + 1);
-
-	// read the first chunk
-	u32 bytes = file.read(&m_rawdata[0], std::min(CACHED_BDF_HASH_SIZE, m_rawsize));
-	if (bytes != std::min(CACHED_BDF_HASH_SIZE, m_rawsize))
+	try
+	{
+		m_rawsize = file.size();
+		std::vector<char>::size_type const sz(m_rawsize + 1);
+		if (u64(sz) != (m_rawsize + 1))
+			return false;
+		m_rawdata.resize(sz);
+	}
+	catch (...)
+	{
 		return false;
+	}
 
-	// has the chunk
-	u32 hash = core_crc32(0, (const u8 *)&m_rawdata[0], bytes) ^ u32(m_rawsize);
+	// read the first chunk and hash it
+	chunk = u32((std::min<u64>)(CACHED_BDF_HASH_SIZE, m_rawsize));
+	bytes = file.read(&m_rawdata[0], chunk);
+	if (bytes != chunk)
+	{
+		m_rawdata.clear();
+		return false;
+	}
+	u32 const hash(core_crc32(0, reinterpret_cast<u8 const *>(&m_rawdata[0]), bytes));
 
 	// create the cached filename, changing the 'F' to a 'C' on the extension
 	std::string cachedname(filename);
-	cachedname.erase(cachedname.length() - 3, 3).append("bdc");
+	if ((4U < cachedname.length()) && !core_stricmp(&cachedname[cachedname.length() - 4], ".bdf"))
+		cachedname.erase(cachedname.length() - 4);
+	cachedname.append(".bdc");
 
 	// attempt to open the cached version of the font
 	{
@@ -508,38 +963,36 @@ bool render_font::load_cached_bdf(const char *filename)
 		if (filerr == osd_file::error::NONE)
 		{
 			// if we have a cached version, load it
-			bool result = load_cached(cachefile, hash);
+			bool const result = load_cached(cachefile, m_rawsize, hash);
 
 			// if that worked, we're done
 			if (result)
-			{
-				// don't do that - glyphs data point into this array ...
-				// m_rawdata.reset();
 				return true;
-			}
 		}
 	}
 
-	// read in the rest of the font
-	if (bytes < m_rawsize)
+	// read in the rest of the font and NUL-terminate it
+	while (bytes < m_rawsize)
 	{
-		u32 read = file.read(&m_rawdata[bytes], m_rawsize - bytes);
-		if (read != m_rawsize - bytes)
+		chunk = u32((std::min<u64>)(std::numeric_limits<u32>::max(), m_rawsize - bytes));
+		u32 const read(file.read(&m_rawdata[bytes], chunk));
+		bytes += read;
+		if (read != chunk)
 		{
 			m_rawdata.clear();
 			return false;
 		}
 	}
-
-	// NULL-terminate the data and attach it to the font
-	m_rawdata[m_rawsize] = 0;
+	m_rawdata[m_rawsize] = '\0';
 
 	// load the BDF
-	bool result = load_bdf();
+	bool const result = load_bdf();
 
 	// if we loaded okay, create a cached one
 	if (result)
-		save_cached(cachedname.c_str(), hash);
+		save_cached(cachedname.c_str(), m_rawsize, hash);
+	else
+		m_rawdata.clear();
 
 	// close the file
 	return result;
@@ -553,109 +1006,344 @@ bool render_font::load_cached_bdf(const char *filename)
 bool render_font::load_bdf()
 {
 	// set the format to text
-	m_format = FF_TEXT;
+	m_format = format::TEXT;
 
-	// first find the FONTBOUNDINGBOX tag
-	const char *ptr;
-	for (ptr = &m_rawdata[0]; ptr != nullptr; ptr = next_line(ptr))
+	bdf_helper<std::vector<char>::const_iterator> helper(std::cbegin(m_rawdata), std::cend(m_rawdata));
+
+	// the first thing we want to see is the STARTFONT declaration, failing that we can't do much
+	for ( ; !helper.is_keyword("STARTFONT"); helper.next_line())
+	{
+		if (helper.at_end())
+		{
+			osd_printf_error("render_font::load_bdf: expected STARTFONT\n");
+			return false;
+		}
+	}
+
+	// parse out the global information we need
+	bool have_bbox(false);
+	bool have_properties(false);
+	bool have_defchar(false);
+	for (helper.next_line(); !helper.is_keyword("CHARS"); helper.next_line())
 	{
-		// we only care about a tiny few fields
-		if (strncmp(ptr, "FONTBOUNDINGBOX ", 16) == 0)
+		if (helper.at_end())
 		{
-			int dummy1, dummy2;
-			if (sscanf(ptr + 16, "%d %d %d %d", &dummy1, &m_height, &dummy2, &m_yoffs) != 4)
+			// font with no characters is useless
+			osd_printf_error("render_font::load_bdf: no glyph section found\n");
+			return false;
+		}
+		else if (helper.is_keyword("FONTBOUNDINGBOX"))
+		{
+			// check for duplicate bounding box
+			if (have_bbox)
+			{
+				osd_printf_error("render_font::load_bdf: found additional bounding box \"%.*s\"\n", int(helper.value_length()), &*helper.value_begin());
 				return false;
-			break;
+			}
+			have_bbox = true;
+
+			// parse bounding box and check that it's at least half sane
+			int width, xoffs;
+			if (4 == sscanf(&*helper.value_begin(), "%d %d %d %d", &width, &m_height, &xoffs, &m_yoffs))
+			{
+				LOG("render_font::load_bdf: got bounding box %dx%d %d,%d\n", width, m_height, xoffs, m_yoffs);
+				if ((0 >= m_height) || (0 >= width))
+				{
+					osd_printf_error("render_font::load_bdf: bounding box is invalid\n");
+					return false;
+				}
+			}
+			else
+			{
+				osd_printf_error("render_font::load_bdf: failed to parse bounding box \"%.*s\"\n", int(helper.value_length()), &*helper.value_begin());
+				return false;
+			}
+		}
+		else if (helper.is_keyword("STARTPROPERTIES"))
+		{
+			// check for duplicated properties section
+			if (have_properties)
+			{
+				osd_printf_error("render_font::load_bdf: found additional properties\n");
+				return false;
+			}
+			have_properties = true;
+
+			// get property count for sanity check
+			int propcount;
+			if (1 != sscanf(&*helper.value_begin(), "%d", &propcount))
+			{
+				osd_printf_error("render_font::load_bdf: failed to parse property count \"%.*s\"\n", int(helper.value_length()), &*helper.value_begin());
+				return false;
+			}
+
+			int actual(0);
+			for (helper.next_line(); !helper.is_keyword("ENDPROPERTIES"); helper.next_line())
+			{
+				++actual;
+				if (helper.at_end())
+				{
+					// unterminated properties section
+					osd_printf_error("render_font::load_bdf: end of properties not found\n");
+					return false;
+				}
+				else if (helper.is_keyword("DEFAULT_CHAR"))
+				{
+					// check for duplicate default character
+					if (have_defchar)
+					{
+						osd_printf_error("render_font::load_bdf: found additional default character \"%.*s\"\n", int(helper.value_length()), &*helper.value_begin());
+						return false;
+					}
+					have_defchar = true;
+
+					// parse default character
+					if (1 == sscanf(&*helper.value_begin(), "%d", &m_defchar))
+					{
+						LOG("render_font::load_bdf: got default character 0x%x\n", m_defchar);
+					}
+					else
+					{
+						osd_printf_error("render_font::load_bdf: failed to parse default character \"%.*s\"\n", int(helper.value_length()), &*helper.value_begin());
+						return false;
+					}
+				}
+			}
+
+			// sanity check on number of properties
+			if (actual != propcount)
+			{
+				osd_printf_error("render_font::load_bdf: incorrect number of properties %d\n", actual);
+				return false;
+			}
 		}
 	}
 
 	// compute the scale factor
-	m_scale = 1.0f / (float)m_height;
+	if (!have_bbox)
+	{
+		osd_printf_error("render_font::load_bdf: no bounding box found\n");
+		return false;
+	}
+	m_scale = 1.0f / float(m_height);
+
+	// get expected character count
+	int expected;
+	if (1 == sscanf(&*helper.value_begin(), "%d", &expected))
+	{
+		LOG("render_font::load_bdf: got character count %d\n", expected);
+	}
+	else
+	{
+		osd_printf_error("render_font::load_bdf: failed to parse character count \"%.*s\"\n", int(helper.value_length()), &*helper.value_begin());
+		return false;
+	}
 
 	// now scan for characters
+	auto const nothex([] (char ch) { return (('0' > ch) || ('9' < ch)) && (('A' > ch) || ('Z' < ch)) && (('a' > ch) || ('z' < ch)); });
 	int charcount = 0;
-	for ( ; ptr != nullptr; ptr = next_line(ptr))
+	for (helper.next_line(); !helper.is_keyword("ENDFONT"); helper.next_line())
 	{
-		// stop at ENDFONT
-		if (strncmp(ptr, "ENDFONT", 7) == 0)
-			break;
-
-		// once we hit a STARTCHAR, parse until the end
-		if (strncmp(ptr, "STARTCHAR ", 10) == 0)
+		if (helper.at_end())
 		{
-			int bmwidth = -1, bmheight = -1, xoffs = -1, yoffs = -1;
-			const char *rawdata = nullptr;
-			int charnum = -1;
-			int width = -1;
-
-			// scan for interesting per-character tags
-			for ( ; ptr != nullptr; ptr = next_line(ptr))
+			// unterminated font
+			osd_printf_error("render_font::load_bdf: end of font not found\n");
+			return false;
+		}
+		else if (helper.is_keyword("STARTCHAR"))
+		{
+			// required glyph properties
+			bool have_encoding(false);
+			bool have_advance(false);
+			bool have_bbounds(false);
+			int encoding(-1);
+			int xadvance(-1);
+			int bbw(-1), bbh(-1), bbxoff(-1), bbyoff(-1);
+
+			// stuff for the bitmap data
+			bool in_bitmap(false);
+			int bitmap_rows(0);
+			char const *bitmap_data(nullptr);
+
+			// parse a glyph
+			for (helper.next_line(); !helper.is_keyword("ENDCHAR"); helper.next_line())
 			{
-				// ENCODING tells us which character
-				if (strncmp(ptr, "ENCODING ", 9) == 0)
+				if (helper.at_end())
 				{
-					if (sscanf(ptr + 9, "%d", &charnum) != 1)
-						return 1;
+					// unterminated glyph
+					osd_printf_error("render_font::load_bdf: end of glyph not found\n");
+					return false;
 				}
-
-				// DWIDTH tells us the width to the next character
-				else if (strncmp(ptr, "DWIDTH ", 7) == 0)
+				else if (in_bitmap)
 				{
-					int dummy1;
-					if (sscanf(ptr + 7, "%d %d", &width, &dummy1) != 2)
-						return 1;
+					// quick sanity check
+					if ((2 * ((bbw + 7) / 8)) != helper.keyword_length())
+					{
+						osd_printf_error("render_font::load_bdf: incorrect length for bitmap line \"%.*s\"\n", int(helper.keyword_length()), &*helper.keyword_begin());
+						return false;
+					}
+					else if (std::find_if(helper.keyword_begin(), helper.keyword_end(), nothex) != helper.keyword_end())
+					{
+						osd_printf_error("render_font::load_bdf: found invalid character in bitmap line \"%.*s\"\n", int(helper.keyword_length()), &*helper.keyword_begin());
+						return false;
+					}
+
+					// track number of rows
+					if (1 == ++bitmap_rows)
+						bitmap_data = &*helper.keyword_begin();
+
 				}
+				else if (helper.is_keyword("ENCODING"))
+				{
+					// check for duplicate glyph encoding
+					if (have_encoding)
+					{
+						osd_printf_error("render_font::load_bdf: found additional glyph encoding \"%.*s\"\n", int(helper.value_length()), &*helper.value_begin());
+						return false;
+					}
+					have_encoding = true;
 
-				// BBX tells us the height/width of the bitmap and the offsets
-				else if (strncmp(ptr, "BBX ", 4) == 0)
+					// need to support Adobe Standard Encoding "123" and non-standard glyph index "-1 123"
+					std::string const value(helper.value_begin(), helper.value_end());
+					int aux;
+					int const cnt(sscanf(value.c_str(), "%d %d", &encoding, &aux));
+					if ((2 == cnt) && (-1 == encoding) && (0 <= aux))
+					{
+						encoding = aux;
+					}
+					else if ((1 != cnt) || (0 > encoding))
+					{
+						osd_printf_error("render_font::load_bdf: failed to parse glyph encoding \"%.*s\"\n", int(helper.value_length()), &*helper.value_begin());
+						return false;
+					}
+					LOG("render_font::load_bdf: got glyph encoding %d\n", encoding);
+				}
+				else if (helper.is_keyword("DWIDTH"))
 				{
-					if (sscanf(ptr + 4, "%d %d %d %d", &bmwidth, &bmheight, &xoffs, &yoffs) != 4)
-						return 1;
+					// check for duplicate advance
+					if (have_advance)
+					{
+						osd_printf_error("render_font::load_bdf: found additional pixel width \"%.*s\"\n", int(helper.value_length()), &*helper.value_begin());
+						return false;
+					}
+					have_advance = true;
+
+					// completely ignore vertical advance
+					int yadvance;
+					if (2 == sscanf(&*helper.value_begin(), "%d %d", &xadvance, &yadvance))
+					{
+						LOG("render_font::load_bdf: got pixel width %d,%d\n", xadvance, yadvance);
+					}
+					else
+					{
+						osd_printf_error("render_font::load_bdf: failed to parse pixel width \"%.*s\"\n", int(helper.value_length()), &*helper.value_begin());
+						return false;
+					}
 				}
+				else if (helper.is_keyword("BBX"))
+				{
+					// check for duplicate black pixel box
+					if (have_bbounds)
+					{
+						osd_printf_error("render_font::load_bdf: found additional pixel width \"%.*s\"\n", int(helper.value_length()), &*helper.value_begin());
+						return false;
+					}
+					have_bbounds = true;
 
-				// BITMAP is the start of the data
-				else if (strncmp(ptr, "BITMAP", 6) == 0)
+					// extract position/size of black pixel area
+					if (4 == sscanf(&*helper.value_begin(), "%d %d %d %d", &bbw, &bbh, &bbxoff, &bbyoff))
+					{
+						LOG("render_font::load_bdf: got black pixel box %dx%d %d,%d\n", bbw, bbh, bbxoff, bbyoff);
+						if ((0 > bbw) || (0 > bbh))
+						{
+							osd_printf_error("render_font::load_bdf: black pixel box is invalid\n");
+							return false;
+						}
+					}
+					else
+					{
+						osd_printf_error("render_font::load_bdf: failed to parse black pixel box \"%.*s\"\n", int(helper.value_length()), &*helper.value_begin());
+						return false;
+					}
+				}
+				else if (helper.is_keyword("BITMAP"))
 				{
-					// stash the raw pointer and scan for the end of the character
-					for (rawdata = ptr = next_line(ptr); ptr != nullptr && strncmp(ptr, "ENDCHAR", 7) != 0; ptr = next_line(ptr)) { }
-					break;
+					// this is the bitmap - we need to already have properties before we get here
+					if (!have_advance)
+					{
+						osd_printf_error("render_font::load_bdf: glyph has no pixel width\n");
+						return false;
+					}
+					else if (!have_bbounds)
+					{
+						osd_printf_error("render_font::load_bdf: glyph has no black pixel box\n");
+						return false;
+					}
+					in_bitmap = true;
 				}
 			}
 
-			// if we have everything, allocate a new character
-			if (charnum >= 0 && charnum < (256 * ARRAY_LENGTH(m_glyphs)) && rawdata != nullptr && bmwidth >= 0 && bmheight >= 0)
+			// now check that we have what we need
+			if (!in_bitmap)
+			{
+				osd_printf_error("render_font::load_bdf: glyph has no bitmap\n");
+				return false;
+			}
+			else if (bitmap_rows != bbh)
+			{
+				osd_printf_error("render_font::load_bdf: incorrect number of bitmap lines %d\n", bitmap_rows);
+				return false;
+			}
+
+			// some kinds of characters will screw us up
+			if (0 > xadvance)
+			{
+				LOG("render_font::load_bdf: ignoring character with negative x advance\n");
+			}
+			else if ((256 * ARRAY_LENGTH(m_glyphs)) <= encoding)
+			{
+				LOG("render_font::load_bdf: ignoring character with encoding outside range\n");
+			}
+			else
 			{
 				// if we don't have a subtable yet, make one
-				if (!m_glyphs[charnum / 256])
-					m_glyphs[charnum / 256] = new glyph[256];
+				if (!m_glyphs[encoding / 256])
+				{
+					try
+					{
+						m_glyphs[encoding / 256] = new glyph[256];
+					}
+					catch (...)
+					{
+						osd_printf_error("render_font::load_bdf: allocation failed\n");
+						return false;
+					}
+				}
 
 				// fill in the entry
-				glyph &gl = m_glyphs[charnum / 256][charnum % 256];
-				gl.width = width;
-				gl.bmwidth = bmwidth;
-				gl.bmheight = bmheight;
-				gl.xoffs = xoffs;
-				gl.yoffs = yoffs;
-				gl.rawdata = rawdata;
+				glyph &gl = m_glyphs[encoding / 256][encoding % 256];
+				gl.width = xadvance;
+				gl.bmwidth = bbw;
+				gl.bmheight = bbh;
+				gl.xoffs = bbxoff;
+				gl.yoffs = bbyoff;
+				gl.rawdata = bitmap_data;
 			}
 
 			// some progress for big fonts
-			if (++charcount % 256 == 0)
+			if (0 == (++charcount % 256))
 				osd_printf_warning("Loading BDF font... (%d characters loaded)\n", charcount);
 		}
 	}
 
-	// make sure all the numbers are the same width
-	if (m_glyphs[0])
+	// check number of characters
+	if (expected != charcount)
 	{
-		int maxwidth = 0;
-		for (int ch = '0'; ch <= '9'; ch++)
-			if (m_glyphs[0][ch].bmwidth > maxwidth)
-				maxwidth = m_glyphs[0][ch].width;
-		for (int ch = '0'; ch <= '9'; ch++)
-			m_glyphs[0][ch].width = maxwidth;
+		osd_printf_error("render_font::load_bdf: incorrect character count %d\n", charcount);
+		return false;
 	}
 
+	// should have bailed by now if something went wrong
 	return true;
 }
 
@@ -664,69 +1352,104 @@ bool render_font::load_bdf()
 //  load_cached - load a font in cached format
 //-------------------------------------------------
 
-bool render_font::load_cached(emu_file &file, u32 hash)
+bool render_font::load_cached(emu_file &file, u64 length, u32 hash)
 {
-	// get the file size
-	u64 filesize = file.size();
-
-	// first read the header
-	u8 header[CACHED_HEADER_SIZE];
-	u32 bytes_read = file.read(header, CACHED_HEADER_SIZE);
-	if (bytes_read != CACHED_HEADER_SIZE)
+	// get the file size, read the header, and check that it looks good
+	u64 const filesize(file.size());
+	bdc_header header;
+	if (!header.read(file))
+	{
+		osd_printf_warning("render_font::load_cached: error reading BDC header\n");
 		return false;
-
-	// validate the header
-	if (header[0] != 'f' || header[1] != 'o' || header[2] != 'n' || header[3] != 't')
+	}
+	else if (!header.check_magic() || (bdc_header::MAJVERSION != header.get_major_version()) || (bdc_header::MINVERSION != header.get_minor_version()))
+	{
+		LOG("render_font::load_cached: incompatible BDC file\n");
 		return false;
-	if (hash && (header[4] != u8(hash >> 24) || header[5] != u8(hash >> 16) || header[6] != u8(hash >> 8) || header[7] != u8(hash)))
+	}
+	else if (length && ((header.get_original_length() != length) || (header.get_original_hash() != hash)))
+	{
+		LOG("render_font::load_cached: BDC file does not match original BDF file\n");
 		return false;
-	m_height = (header[8] << 8) | header[9];
-	m_scale = 1.0f / (float)m_height;
-	m_yoffs = s16((header[10] << 8) | header[11]);
-	u32 numchars = (header[12] << 24) | (header[13] << 16) | (header[14] << 8) | header[15];
-	if (filesize - CACHED_HEADER_SIZE < numchars * CACHED_CHAR_SIZE)
+	}
+
+	// get global properties from the header
+	m_height = header.get_height();
+	m_scale = 1.0f / float(m_height);
+	m_yoffs = header.get_y_offset();
+	m_defchar = header.get_default_character();
+	u32 const numchars(header.get_glyph_count());
+	if ((file.tell() + (u64(numchars) * bdc_table_entry::size())) > filesize)
+	{
+		LOG("render_font::load_cached: BDC file is too small to hold glyph table\n");
 		return false;
+	}
 
 	// now read the rest of the data
-	m_rawdata.resize(filesize - CACHED_HEADER_SIZE);
-	bytes_read = file.read(&m_rawdata[0], filesize - CACHED_HEADER_SIZE);
-	if (bytes_read != filesize - CACHED_HEADER_SIZE)
+	u64 const remaining(filesize - file.tell());
+	try
 	{
-		m_rawdata.clear();
-		return false;
+		m_rawdata.resize(std::size_t(remaining));
+	}
+	catch (...)
+	{
+		osd_printf_error("render_font::load_cached: allocation error\n");
+	}
+	for (u64 bytes_read = 0; remaining > bytes_read; )
+	{
+		u32 const chunk((std::min)(u64(std::numeric_limits<u32>::max()), remaining));
+		if (file.read(&m_rawdata[bytes_read], chunk) != chunk)
+		{
+			osd_printf_error("render_font::load_cached: error reading BDC data\n");
+			m_rawdata.clear();
+			return false;
+		}
+		bytes_read += chunk;
 	}
 
 	// extract the data from the data
-	u64 offset = numchars * CACHED_CHAR_SIZE;
-	for (int chindex = 0; chindex < numchars; chindex++)
+	std::size_t offset(std::size_t(numchars) * bdc_table_entry::size());
+	bdc_table_entry entry(m_rawdata.empty() ? nullptr : &m_rawdata[0]);
+	for (unsigned chindex = 0; chindex < numchars; chindex++, entry = entry.get_next())
 	{
-		const u8 *info = reinterpret_cast<u8 *>(&m_rawdata[chindex * CACHED_CHAR_SIZE]);
-		int chnum = (info[0] << 8) | info[1];
-
 		// if we don't have a subtable yet, make one
+		int const chnum(entry.get_encoding());
+		LOG("render_font::load_cached: loading character %d\n", chnum);
 		if (!m_glyphs[chnum / 256])
-			m_glyphs[chnum / 256] = new glyph[256];
+		{
+			try
+			{
+				m_glyphs[chnum / 256] = new glyph[256];
+			}
+			catch (...)
+			{
+				osd_printf_error("render_font::load_cached: allocation error\n");
+				m_rawdata.clear();
+				return false;
+			}
+		}
 
 		// fill in the entry
 		glyph &gl = m_glyphs[chnum / 256][chnum % 256];
-		gl.width = (info[2] << 8) | info[3];
-		gl.xoffs = s16((info[4] << 8) | info[5]);
-		gl.yoffs = s16((info[6] << 8) | info[7]);
-		gl.bmwidth = (info[8] << 8) | info[9];
-		gl.bmheight = (info[10] << 8) | info[11];
+		gl.width = entry.get_x_advance();
+		gl.xoffs = entry.get_bb_x_offset();
+		gl.yoffs = entry.get_bb_y_offset();
+		gl.bmwidth = entry.get_bb_width();
+		gl.bmheight = entry.get_bb_height();
 		gl.rawdata = &m_rawdata[offset];
 
 		// advance the offset past the character
 		offset += (gl.bmwidth * gl.bmheight + 7) / 8;
-		if (offset > filesize - CACHED_HEADER_SIZE)
+		if (m_rawdata.size() < offset)
 		{
+			osd_printf_verbose("render_font::load_cached: BDC file too small to hold all glyphs\n");
 			m_rawdata.clear();
 			return false;
 		}
 	}
 
-	// reuse the chartable as a temporary buffer
-	m_format = FF_CACHED;
+	// got everything
+	m_format = format::CACHED;
 	return true;
 }
 
@@ -735,76 +1458,73 @@ bool render_font::load_cached(emu_file &file, u32 hash)
 //  save_cached - save a font in cached format
 //-------------------------------------------------
 
-bool render_font::save_cached(const char *filename, u32 hash)
+bool render_font::save_cached(const char *filename, u64 length, u32 hash)
 {
 	osd_printf_warning("Generating cached BDF font...\n");
 
 	// attempt to open the file
 	emu_file file(m_manager.machine().options().font_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE);
-	osd_file::error filerr = file.open(filename);
-	if (filerr != osd_file::error::NONE)
+	osd_file::error const filerr = file.open(filename);
+	if (osd_file::error::NONE != filerr)
 		return false;
 
-	// determine the number of characters
-	int numchars = 0;
-	for (int chnum = 0; chnum < (256 * ARRAY_LENGTH(m_glyphs)); chnum++)
+	// count glyphs
+	unsigned numchars = 0;
+	for (glyph const *const page : m_glyphs)
 	{
-		if (m_glyphs[chnum / 256])
+		for (unsigned chnum = 0; page && (256 > chnum); ++chnum)
 		{
-			glyph &gl = m_glyphs[chnum / 256][chnum % 256];
-			if (gl.width > 0)
-				numchars++;
+			if (0 < page[chnum].width)
+				++numchars;
 		}
 	}
+	LOG("render_font::save_cached: %u glyphs with positive advance to save\n", numchars);
 
 	try
 	{
+		u32 bytes_written;
+
+		{
+			LOG("render_font::save_cached: writing header\n");
+			bdc_header hdr;
+			hdr.set_magic();
+			hdr.set_version();
+			hdr.set_original_length(length);
+			hdr.set_original_hash(hash);
+			hdr.set_glyph_count(numchars);
+			hdr.set_height(m_height);
+			hdr.set_y_offset(m_yoffs);
+			hdr.set_default_character(m_defchar);
+			if (!hdr.write(file))
+				throw emu_fatalerror("Error writing cached file");
+		}
+		u64 const table_offs(file.tell());
+
 		// allocate an array to hold the character data
-		std::vector<u8> chartable(numchars * CACHED_CHAR_SIZE, 0);
+		std::vector<u8> chartable(std::size_t(numchars) * bdc_table_entry::size(), 0);
 
 		// allocate a temp buffer to compress into
 		std::vector<u8> tempbuffer(65536);
 
-		// write the header
-		u8 *dest = &tempbuffer[0];
-		*dest++ = 'f';
-		*dest++ = 'o';
-		*dest++ = 'n';
-		*dest++ = 't';
-		*dest++ = hash >> 24;
-		*dest++ = hash >> 16;
-		*dest++ = hash >> 8;
-		*dest++ = hash & 0xff;
-		*dest++ = m_height >> 8;
-		*dest++ = m_height & 0xff;
-		*dest++ = m_yoffs >> 8;
-		*dest++ = m_yoffs & 0xff;
-		*dest++ = numchars >> 24;
-		*dest++ = numchars >> 16;
-		*dest++ = numchars >> 8;
-		*dest++ = numchars & 0xff;
-		assert(dest == &tempbuffer[CACHED_HEADER_SIZE]);
-		u32 bytes_written = file.write(&tempbuffer[0], CACHED_HEADER_SIZE);
-		if (bytes_written != dest - &tempbuffer[0])
-			throw emu_fatalerror("Error writing cached file");
-
 		// write the empty table to the beginning of the file
-		bytes_written = file.write(&chartable[0], numchars * CACHED_CHAR_SIZE);
-		if (bytes_written != numchars * CACHED_CHAR_SIZE)
+		bytes_written = file.write(&chartable[0], chartable.size());
+		if (bytes_written != chartable.size())
 			throw emu_fatalerror("Error writing cached file");
 
 		// loop over all characters
-		int tableindex = 0;
-		for (int chnum = 0; chnum < (256 * ARRAY_LENGTH(m_glyphs)); chnum++)
+		bdc_table_entry table_entry(chartable.empty() ? nullptr : &chartable[0]);
+		for (unsigned chnum = 0; chnum < (256 * ARRAY_LENGTH(m_glyphs)); chnum++)
 		{
-			glyph &gl = get_char(chnum);
-			if (gl.width > 0)
+			if (m_glyphs[chnum / 256] && (0 < m_glyphs[chnum / 256][chnum % 256].width))
 			{
+				LOG("render_font::save_cached: writing glyph %u\n", chnum);
+				glyph &gl(get_char(chnum));
+
 				// write out a bit-compressed bitmap if we have one
 				if (gl.bitmap.valid())
 				{
 					// write the data to the tempbuffer
-					dest = &tempbuffer[0];
+					u8 *dest = &tempbuffer[0];
 					u8 accum = 0;
 					u8 accbit = 7;
 
@@ -842,27 +1562,34 @@ bool render_font::save_cached(const char *filename, u32 hash)
 				}
 
 				// compute the table entry
-				dest = &chartable[tableindex++ * CACHED_CHAR_SIZE];
-				*dest++ = chnum >> 8;
-				*dest++ = chnum & 0xff;
-				*dest++ = gl.width >> 8;
-				*dest++ = gl.width & 0xff;
-				*dest++ = gl.xoffs >> 8;
-				*dest++ = gl.xoffs & 0xff;
-				*dest++ = gl.yoffs >> 8;
-				*dest++ = gl.yoffs & 0xff;
-				*dest++ = gl.bmwidth >> 8;
-				*dest++ = gl.bmwidth & 0xff;
-				*dest++ = gl.bmheight >> 8;
-				*dest++ = gl.bmheight & 0xff;
+				table_entry.set_encoding(chnum);
+				table_entry.set_x_advance(gl.width);
+				table_entry.set_bb_x_offset(gl.xoffs);
+				table_entry.set_bb_y_offset(gl.yoffs);
+				table_entry.set_bb_width(gl.bmwidth);
+				table_entry.set_bb_height(gl.bmheight);
+				table_entry = table_entry.get_next();
 			}
 		}
 
 		// seek back to the beginning and rewrite the table
-		file.seek(CACHED_HEADER_SIZE, SEEK_SET);
-		bytes_written = file.write(&chartable[0], numchars * CACHED_CHAR_SIZE);
-		if (bytes_written != numchars * CACHED_CHAR_SIZE)
-			throw emu_fatalerror("Error writing cached file");
+		if (!chartable.empty())
+		{
+			LOG("render_font::save_cached: writing character table\n");
+			file.seek(table_offs, SEEK_SET);
+			u8 const *bytes(&chartable[0]);
+			for (u64 remaining = chartable.size(); remaining; )
+			{
+				u32 const chunk((std::min<u64>)(std::numeric_limits<u32>::max(), remaining));
+				bytes_written = file.write(bytes, chunk);
+				if (chunk != bytes_written)
+					throw emu_fatalerror("Error writing cached file");
+				bytes += chunk;
+				remaining -= chunk;
+			}
+		}
+
+		// no trouble?
 		return true;
 	}
 	catch (...)
@@ -871,3 +1598,99 @@ bool render_font::save_cached(const char *filename, u32 hash)
 		return false;
 	}
 }
+
+
+void render_font::render_font_command_glyph()
+{
+	// FIXME: this is copy/pasta from the BDC loading, and it shouldn't be injected into every font
+	emu_file file(OPEN_FLAG_READ);
+	if (file.open_ram(font_uicmd14, sizeof(font_uicmd14)) == osd_file::error::NONE)
+	{
+		// get the file size, read the header, and check that it looks good
+		u64 const filesize(file.size());
+		bdc_header header;
+		if (!header.read(file))
+		{
+			osd_printf_warning("render_font::render_font_command_glyph: error reading BDC header\n");
+			return;
+		}
+		else if (!header.check_magic() || (bdc_header::MAJVERSION != header.get_major_version()) || (bdc_header::MINVERSION != header.get_minor_version()))
+		{
+			LOG("render_font::render_font_command_glyph: incompatible BDC file\n");
+			return;
+		}
+
+		// get global properties from the header
+		m_height_cmd = header.get_height();
+		m_yoffs_cmd = header.get_y_offset();
+		u32 const numchars(header.get_glyph_count());
+		if ((file.tell() + (u64(numchars) * bdc_table_entry::size())) > filesize)
+		{
+			LOG("render_font::render_font_command_glyph: BDC file is too small to hold glyph table\n");
+			return;
+		}
+
+		// now read the rest of the data
+		u64 const remaining(filesize - file.tell());
+		try
+		{
+			m_rawdata_cmd.resize(std::size_t(remaining));
+		}
+		catch (...)
+		{
+			osd_printf_error("render_font::render_font_command_glyph: allocation error\n");
+		}
+		for (u64 bytes_read = 0; remaining > bytes_read; )
+		{
+			u32 const chunk((std::min)(u64(std::numeric_limits<u32>::max()), remaining));
+			if (file.read(&m_rawdata_cmd[bytes_read], chunk) != chunk)
+			{
+				osd_printf_error("render_font::render_font_command_glyph: error reading BDC data\n");
+				m_rawdata_cmd.clear();
+				return;
+			}
+			bytes_read += chunk;
+		}
+
+		// extract the data from the data
+		std::size_t offset(std::size_t(numchars) * bdc_table_entry::size());
+		bdc_table_entry entry(m_rawdata_cmd.empty() ? nullptr : &m_rawdata_cmd[0]);
+		for (unsigned chindex = 0; chindex < numchars; chindex++, entry = entry.get_next())
+		{
+			// if we don't have a subtable yet, make one
+			int const chnum(entry.get_encoding());
+			LOG("render_font::render_font_command_glyph: loading character %d\n", chnum);
+			if (!m_glyphs_cmd[chnum / 256])
+			{
+				try
+				{
+					m_glyphs_cmd[chnum / 256] = new glyph[256];
+				}
+				catch (...)
+				{
+					osd_printf_error("render_font::render_font_command_glyph: allocation error\n");
+					m_rawdata_cmd.clear();
+					return;
+				}
+			}
+
+			// fill in the entry
+			glyph &gl = m_glyphs_cmd[chnum / 256][chnum % 256];
+			gl.width = entry.get_x_advance();
+			gl.xoffs = entry.get_bb_x_offset();
+			gl.yoffs = entry.get_bb_y_offset();
+			gl.bmwidth = entry.get_bb_width();
+			gl.bmheight = entry.get_bb_height();
+			gl.rawdata = &m_rawdata_cmd[offset];
+
+			// advance the offset past the character
+			offset += (gl.bmwidth * gl.bmheight + 7) / 8;
+			if (m_rawdata_cmd.size() < offset)
+			{
+				osd_printf_verbose("render_font::render_font_command_glyph: BDC file too small to hold all glyphs\n");
+				m_rawdata_cmd.clear();
+				return;
+			}
+		}
+	}
+}
diff --git a/src/emu/rendfont.h b/src/emu/rendfont.h
index 558b5c5..5893888 100644
--- a/src/emu/rendfont.h
+++ b/src/emu/rendfont.h
@@ -1,5 +1,5 @@
 // license:BSD-3-Clause
-// copyright-holders:Aaron Giles
+// copyright-holders:Aaron Giles, Vas Crabb
 /***************************************************************************
 
     rendfont.h
@@ -8,8 +8,8 @@
 
 ***************************************************************************/
 
-#ifndef __RENDFONT_H__
-#define __RENDFONT_H__
+#ifndef MAME_EMU_RENDFONT_H
+#define MAME_EMU_RENDFONT_H
 
 #include "render.h"
 
@@ -53,11 +53,15 @@ private:
 	{
 	public:
 		glyph()
-			: width(0),
-				xoffs(0), yoffs(0),
-				bmwidth(0), bmheight(0),
-				rawdata(nullptr),
-				texture(nullptr) { }
+			: width(-1)
+			, xoffs(-1), yoffs(-1)
+			, bmwidth(0), bmheight(0)
+			, rawdata(nullptr)
+			, texture(nullptr)
+			, bitmap()
+			, color()
+		{
+		}
 
 		s32                 width;              // width from this character to the next
 		s32                 xoffs, yoffs;       // X and Y offset from baseline to top,left of bitmap
@@ -67,16 +71,15 @@ private:
 		bitmap_argb32       bitmap;             // pointer to the bitmap containing the raw data
 
 		rgb_t               color;
-
 	};
 
 	// internal format
-	enum format
+	enum class format
 	{
-		FF_UNKNOWN,
-		FF_TEXT,
-		FF_CACHED,
-		FF_OSD
+		UNKNOWN,
+		TEXT,
+		CACHED,
+		OSD
 	};
 
 	// helpers
@@ -84,9 +87,8 @@ private:
 	void char_expand(char32_t chnum, glyph &ch);
 	bool load_cached_bdf(const char *filename);
 	bool load_bdf();
-	bool load_cached(emu_file &file, u32 hash);
-	bool load_cached_cmd(emu_file &file, u32 hash);
-	bool save_cached(const char *filename, u32 hash);
+	bool load_cached(emu_file &file, u64 length, u32 hash);
+	bool save_cached(const char *filename, u64 length, u32 hash);
 
 	void render_font_command_glyph();
 
@@ -95,6 +97,7 @@ private:
 	format              m_format;           // format of font data
 	int                 m_height;           // height of the font, from ascent to descent
 	int                 m_yoffs;            // y offset from baseline to descent
+	int                 m_defchar;          // default substitute character
 	float               m_scale;            // 1 / height precomputed
 	glyph               *m_glyphs[17*256];  // array of glyph subtables
 	std::vector<char>   m_rawdata;          // pointer to the raw data for the font
@@ -107,11 +110,9 @@ private:
 	std::vector<char>   m_rawdata_cmd;      // pointer to the raw data for the font
 
 	// constants
-	static const int CACHED_CHAR_SIZE       = 12;
-	static const int CACHED_HEADER_SIZE     = 16;
 	static const u64 CACHED_BDF_HASH_SIZE   = 1024;
 };
 
 void convert_command_glyph(std::string &s);
 
-#endif  /* __RENDFONT_H__ */
+#endif  /* MAME_EMU_RENDFONT_H */
diff --git a/src/emu/rendlay.cpp b/src/emu/rendlay.cpp
index b917b95..5785f5f 100644
--- a/src/emu/rendlay.cpp
+++ b/src/emu/rendlay.cpp
@@ -222,7 +222,7 @@ static int get_variable_value(running_machine &machine, const char *string, char
 //  substitution
 //-------------------------------------------------
 
-static const char *xml_get_attribute_string_with_subst(running_machine &machine, xml_data_node const &node, const char *attribute, const char *defvalue)
+static const char *xml_get_attribute_string_with_subst(running_machine &machine, util::xml::data_node const &node, const char *attribute, const char *defvalue)
 {
 	const char *str = node.get_attribute_string(attribute, nullptr);
 	static char buffer[1000];
@@ -259,7 +259,7 @@ static const char *xml_get_attribute_string_with_subst(running_machine &machine,
 //  substitution
 //-------------------------------------------------
 
-static int xml_get_attribute_int_with_subst(running_machine &machine, xml_data_node const &node, const char *attribute, int defvalue)
+static int xml_get_attribute_int_with_subst(running_machine &machine, util::xml::data_node const &node, const char *attribute, int defvalue)
 {
 	const char *string = xml_get_attribute_string_with_subst(machine, node, attribute, nullptr);
 	int value;
@@ -283,7 +283,7 @@ static int xml_get_attribute_int_with_subst(running_machine &machine, xml_data_n
 //  substitution
 //-------------------------------------------------
 
-static float xml_get_attribute_float_with_subst(running_machine &machine, xml_data_node const &node, const char *attribute, float defvalue)
+static float xml_get_attribute_float_with_subst(running_machine &machine, util::xml::data_node const &node, const char *attribute, float defvalue)
 {
 	const char *string = xml_get_attribute_string_with_subst(machine, node, attribute, nullptr);
 	float value;
@@ -298,7 +298,7 @@ static float xml_get_attribute_float_with_subst(running_machine &machine, xml_da
 //  parse_bounds - parse a bounds XML node
 //-------------------------------------------------
 
-void parse_bounds(running_machine &machine, xml_data_node const *boundsnode, render_bounds &bounds)
+void parse_bounds(running_machine &machine, util::xml::data_node const *boundsnode, render_bounds &bounds)
 {
 	// skip if nothing
 	if (boundsnode == nullptr)
@@ -339,7 +339,7 @@ void parse_bounds(running_machine &machine, xml_data_node const *boundsnode, ren
 //  parse_color - parse a color XML node
 //-------------------------------------------------
 
-void parse_color(running_machine &machine, xml_data_node const *colornode, render_color &color)
+void parse_color(running_machine &machine, util::xml::data_node const *colornode, render_color &color)
 {
 	// skip if nothing
 	if (colornode == nullptr)
@@ -367,7 +367,7 @@ void parse_color(running_machine &machine, xml_data_node const *colornode, rende
 //  node
 //-------------------------------------------------
 
-static void parse_orientation(running_machine &machine, xml_data_node const *orientnode, int &orientation)
+static void parse_orientation(running_machine &machine, util::xml::data_node const *orientnode, int &orientation)
 {
 	// skip if nothing
 	if (orientnode == nullptr)
@@ -422,7 +422,7 @@ layout_element::make_component_map const layout_element::s_make_component{
 //  layout_element - constructor
 //-------------------------------------------------
 
-layout_element::layout_element(running_machine &machine, xml_data_node const &elemnode, const char *dirname)
+layout_element::layout_element(running_machine &machine, util::xml::data_node const &elemnode, const char *dirname)
 	: m_next(nullptr),
 		m_machine(machine),
 		m_defstate(0),
@@ -440,7 +440,7 @@ layout_element::layout_element(running_machine &machine, xml_data_node const &el
 	// parse components in order
 	bool first = true;
 	render_bounds bounds = { 0 };
-	for (xml_data_node const *compnode = elemnode.get_first_child(); compnode; compnode = compnode->get_next_sibling())
+	for (util::xml::data_node const *compnode = elemnode.get_first_child(); compnode; compnode = compnode->get_next_sibling())
 	{
 		make_component_map::const_iterator const make_func(s_make_component.find(compnode->get_name()));
 		if (make_func == s_make_component.end())
@@ -539,7 +539,7 @@ void layout_element::element_scale(bitmap_argb32 &dest, bitmap_argb32 &source, c
 //-------------------------------------------------
 
 template <typename T>
-layout_element::component::ptr layout_element::make_component(running_machine &machine, xml_data_node const &compnode, const char *dirname)
+layout_element::component::ptr layout_element::make_component(running_machine &machine, util::xml::data_node const &compnode, const char *dirname)
 {
 	return std::make_unique<T>(machine, compnode, dirname);
 }
@@ -551,7 +551,7 @@ layout_element::component::ptr layout_element::make_component(running_machine &m
 //-------------------------------------------------
 
 template <int D>
-layout_element::component::ptr layout_element::make_dotmatrix_component(running_machine &machine, xml_data_node const &compnode, const char *dirname)
+layout_element::component::ptr layout_element::make_dotmatrix_component(running_machine &machine, util::xml::data_node const &compnode, const char *dirname)
 {
 	return std::make_unique<dotmatrix_component>(D, machine, compnode, dirname);
 }
@@ -614,7 +614,7 @@ layout_element::texture &layout_element::texture::operator=(texture &&that)
 //  component - constructor
 //-------------------------------------------------
 
-layout_element::component::component(running_machine &machine, xml_data_node const &compnode, const char *dirname)
+layout_element::component::component(running_machine &machine, util::xml::data_node const &compnode, const char *dirname)
 	: m_state(0)
 {
 	// fetch common data
@@ -641,7 +641,7 @@ void layout_element::component::normalize_bounds(float xoffs, float yoffs, float
 //  image_component - constructor
 //-------------------------------------------------
 
-layout_element::image_component::image_component(running_machine &machine, xml_data_node const &compnode, const char *dirname)
+layout_element::image_component::image_component(running_machine &machine, util::xml::data_node const &compnode, const char *dirname)
 	: component(machine, compnode, dirname)
 	, m_hasalpha(false)
 {
@@ -709,7 +709,7 @@ void layout_element::image_component::load_bitmap()
 //  text_component - constructor
 //-------------------------------------------------
 
-layout_element::text_component::text_component(running_machine &machine, xml_data_node const &compnode, const char *dirname)
+layout_element::text_component::text_component(running_machine &machine, util::xml::data_node const &compnode, const char *dirname)
 	: component(machine, compnode, dirname)
 {
 	m_string = xml_get_attribute_string_with_subst(machine, compnode, "string", "");
@@ -733,7 +733,7 @@ void layout_element::text_component::draw(running_machine &machine, bitmap_argb3
 //  dotmatrix_component - constructor
 //-------------------------------------------------
 
-layout_element::dotmatrix_component::dotmatrix_component(int dots, running_machine &machine, xml_data_node const &compnode, const char *dirname)
+layout_element::dotmatrix_component::dotmatrix_component(int dots, running_machine &machine, util::xml::data_node const &compnode, const char *dirname)
 	: component(machine, compnode, dirname),
 		m_dots(dots)
 {
@@ -769,7 +769,7 @@ void layout_element::dotmatrix_component::draw(running_machine &machine, bitmap_
 //  simplecounter_component - constructor
 //-------------------------------------------------
 
-layout_element::simplecounter_component::simplecounter_component(running_machine &machine, xml_data_node const &compnode, const char *dirname)
+layout_element::simplecounter_component::simplecounter_component(running_machine &machine, util::xml::data_node const &compnode, const char *dirname)
 	: component(machine, compnode, dirname)
 {
 	m_digits = xml_get_attribute_int_with_subst(machine, compnode, "digits", 2);
@@ -795,7 +795,7 @@ void layout_element::simplecounter_component::draw(running_machine &machine, bit
 //  reel_component - constructor
 //-------------------------------------------------
 
-layout_element::reel_component::reel_component(running_machine &machine, xml_data_node const &compnode, const char *dirname)
+layout_element::reel_component::reel_component(running_machine &machine, util::xml::data_node const &compnode, const char *dirname)
 	: component(machine, compnode, dirname)
 {
 	for (auto & elem : m_hasalpha)
@@ -1203,7 +1203,7 @@ void layout_element::reel_component::load_reel_bitmap(int number)
 //  led7seg_component - constructor
 //-------------------------------------------------
 
-layout_element::led7seg_component::led7seg_component(running_machine &machine, xml_data_node const &compnode, const char *dirname)
+layout_element::led7seg_component::led7seg_component(running_machine &machine, util::xml::data_node const &compnode, const char *dirname)
 	: component(machine, compnode, dirname)
 {
 }
@@ -1264,7 +1264,7 @@ void layout_element::led7seg_component::draw(running_machine &machine, bitmap_ar
 //  led8seg_gts1_component - constructor
 //-------------------------------------------------
 
-layout_element::led8seg_gts1_component::led8seg_gts1_component(running_machine &machine, xml_data_node const &compnode, const char *dirname)
+layout_element::led8seg_gts1_component::led8seg_gts1_component(running_machine &machine, util::xml::data_node const &compnode, const char *dirname)
 	: component(machine, compnode, dirname)
 {
 }
@@ -1331,7 +1331,7 @@ void layout_element::led8seg_gts1_component::draw(running_machine &machine, bitm
 //  led14seg_component - constructor
 //-------------------------------------------------
 
-layout_element::led14seg_component::led14seg_component(running_machine &machine, xml_data_node const &compnode, const char *dirname)
+layout_element::led14seg_component::led14seg_component(running_machine &machine, util::xml::data_node const &compnode, const char *dirname)
 	: component(machine, compnode, dirname)
 {
 }
@@ -1442,7 +1442,7 @@ void layout_element::led14seg_component::draw(running_machine &machine, bitmap_a
 //  led14segsc_component - constructor
 //-------------------------------------------------
 
-layout_element::led14segsc_component::led14segsc_component(running_machine &machine, xml_data_node const &compnode, const char *dirname)
+layout_element::led14segsc_component::led14segsc_component(running_machine &machine, util::xml::data_node const &compnode, const char *dirname)
 	: component(machine, compnode, dirname)
 {
 }
@@ -1562,7 +1562,7 @@ void layout_element::led14segsc_component::draw(running_machine &machine, bitmap
 //  led16seg_component - constructor
 //-------------------------------------------------
 
-layout_element::led16seg_component::led16seg_component(running_machine &machine, xml_data_node const &compnode, const char *dirname)
+layout_element::led16seg_component::led16seg_component(running_machine &machine, util::xml::data_node const &compnode, const char *dirname)
 	: component(machine, compnode, dirname)
 {
 }
@@ -1683,7 +1683,7 @@ void layout_element::led16seg_component::draw(running_machine &machine, bitmap_a
 //  led16segsc_component - constructor
 //-------------------------------------------------
 
-layout_element::led16segsc_component::led16segsc_component(running_machine &machine, xml_data_node const &compnode, const char *dirname)
+layout_element::led16segsc_component::led16segsc_component(running_machine &machine, util::xml::data_node const &compnode, const char *dirname)
 	: component(machine, compnode, dirname)
 {
 }
@@ -1813,7 +1813,7 @@ void layout_element::led16segsc_component::draw(running_machine &machine, bitmap
 //  rect_component - constructor
 //-------------------------------------------------
 
-layout_element::rect_component::rect_component(running_machine &machine, xml_data_node const &compnode, const char *dirname)
+layout_element::rect_component::rect_component(running_machine &machine, util::xml::data_node const &compnode, const char *dirname)
 	: component(machine, compnode, dirname)
 {
 }
@@ -1859,7 +1859,7 @@ void layout_element::rect_component::draw(running_machine &machine, bitmap_argb3
 //  disk_component - constructor
 //-------------------------------------------------
 
-layout_element::disk_component::disk_component(running_machine &machine, xml_data_node const &compnode, const char *dirname)
+layout_element::disk_component::disk_component(running_machine &machine, util::xml::data_node const &compnode, const char *dirname)
 	: component(machine, compnode, dirname)
 {
 }
@@ -2213,7 +2213,7 @@ const simple_list<layout_view::item> layout_view::s_null_list;
 //  layout_view - constructor
 //-------------------------------------------------
 
-layout_view::layout_view(running_machine &machine, xml_data_node const &viewnode, simple_list<layout_element> &elemlist)
+layout_view::layout_view(running_machine &machine, util::xml::data_node const &viewnode, simple_list<layout_element> &elemlist)
 	: m_next(nullptr)
 	, m_aspect(1.0f)
 	, m_scraspect(1.0f)
@@ -2222,33 +2222,33 @@ layout_view::layout_view(running_machine &machine, xml_data_node const &viewnode
 	m_name = xml_get_attribute_string_with_subst(machine, viewnode, "name", "");
 
 	// if we have a bounds item, load it
-	xml_data_node const *const boundsnode = viewnode.get_child("bounds");
+	util::xml::data_node const *const boundsnode = viewnode.get_child("bounds");
 	m_expbounds.x0 = m_expbounds.y0 = m_expbounds.x1 = m_expbounds.y1 = 0;
 	if (boundsnode != nullptr)
 		parse_bounds(machine, boundsnode, m_expbounds);
 
 	// load backdrop items
-	for (xml_data_node const *itemnode = viewnode.get_child("backdrop"); itemnode != nullptr; itemnode = itemnode->get_next_sibling("backdrop"))
+	for (util::xml::data_node const *itemnode = viewnode.get_child("backdrop"); itemnode != nullptr; itemnode = itemnode->get_next_sibling("backdrop"))
 		m_backdrop_list.append(*global_alloc(item(machine, *itemnode, elemlist)));
 
 	// load screen items
-	for (xml_data_node const *itemnode = viewnode.get_child("screen"); itemnode != nullptr; itemnode = itemnode->get_next_sibling("screen"))
+	for (util::xml::data_node const *itemnode = viewnode.get_child("screen"); itemnode != nullptr; itemnode = itemnode->get_next_sibling("screen"))
 		m_screen_list.append(*global_alloc(item(machine, *itemnode, elemlist)));
 
 	// load overlay items
-	for (xml_data_node const *itemnode = viewnode.get_child("overlay"); itemnode != nullptr; itemnode = itemnode->get_next_sibling("overlay"))
+	for (util::xml::data_node const *itemnode = viewnode.get_child("overlay"); itemnode != nullptr; itemnode = itemnode->get_next_sibling("overlay"))
 		m_overlay_list.append(*global_alloc(item(machine, *itemnode, elemlist)));
 
 	// load bezel items
-	for (xml_data_node const *itemnode = viewnode.get_child("bezel"); itemnode != nullptr; itemnode = itemnode->get_next_sibling("bezel"))
+	for (util::xml::data_node const *itemnode = viewnode.get_child("bezel"); itemnode != nullptr; itemnode = itemnode->get_next_sibling("bezel"))
 		m_bezel_list.append(*global_alloc(item(machine, *itemnode, elemlist)));
 
 	// load cpanel items
-	for (xml_data_node const *itemnode = viewnode.get_child("cpanel"); itemnode != nullptr; itemnode = itemnode->get_next_sibling("cpanel"))
+	for (util::xml::data_node const *itemnode = viewnode.get_child("cpanel"); itemnode != nullptr; itemnode = itemnode->get_next_sibling("cpanel"))
 		m_cpanel_list.append(*global_alloc(item(machine, *itemnode, elemlist)));
 
 	// load marquee items
-	for (xml_data_node const *itemnode = viewnode.get_child("marquee"); itemnode != nullptr; itemnode = itemnode->get_next_sibling("marquee"))
+	for (util::xml::data_node const *itemnode = viewnode.get_child("marquee"); itemnode != nullptr; itemnode = itemnode->get_next_sibling("marquee"))
 		m_marquee_list.append(*global_alloc(item(machine, *itemnode, elemlist)));
 
 	// recompute the data for the view based on a default layer config
@@ -2410,7 +2410,7 @@ void layout_view::resolve_tags()
 //  item - constructor
 //-------------------------------------------------
 
-layout_view::item::item(running_machine &machine, xml_data_node const &itemnode, simple_list<layout_element> &elemlist)
+layout_view::item::item(running_machine &machine, util::xml::data_node const &itemnode, simple_list<layout_element> &elemlist)
 	: m_next(nullptr)
 	, m_element(nullptr)
 	, m_input_port(nullptr)
@@ -2542,11 +2542,11 @@ void layout_view::item::resolve_tags()
 //  layout_file - constructor
 //-------------------------------------------------
 
-layout_file::layout_file(running_machine &machine, xml_data_node const &rootnode, const char *dirname)
+layout_file::layout_file(running_machine &machine, util::xml::data_node const &rootnode, const char *dirname)
 	: m_next(nullptr)
 {
 	// find the layout node
-	xml_data_node const *const mamelayoutnode = rootnode.get_child("mamelayout");
+	util::xml::data_node const *const mamelayoutnode = rootnode.get_child("mamelayout");
 	if (mamelayoutnode == nullptr)
 		throw emu_fatalerror("Invalid XML file: missing mamelayout node");
 
@@ -2556,11 +2556,11 @@ layout_file::layout_file(running_machine &machine, xml_data_node const &rootnode
 		throw emu_fatalerror("Invalid XML file: unsupported version");
 
 	// parse all the elements
-	for (xml_data_node const *elemnode = mamelayoutnode->get_child("element"); elemnode != nullptr; elemnode = elemnode->get_next_sibling("element"))
+	for (util::xml::data_node const *elemnode = mamelayoutnode->get_child("element"); elemnode != nullptr; elemnode = elemnode->get_next_sibling("element"))
 		m_elemlist.append(*global_alloc(layout_element(machine, *elemnode, dirname)));
 
 	// parse all the views
-	for (xml_data_node const *viewnode = mamelayoutnode->get_child("view"); viewnode != nullptr; viewnode = viewnode->get_next_sibling("view"))
+	for (util::xml::data_node const *viewnode = mamelayoutnode->get_child("view"); viewnode != nullptr; viewnode = viewnode->get_next_sibling("view"))
 		m_viewlist.append(*global_alloc(layout_view(machine, *viewnode, m_elemlist)));
 }
 
diff --git a/src/emu/sound.cpp b/src/emu/sound.cpp
index d22ee99..1f3373c 100644
--- a/src/emu/sound.cpp
+++ b/src/emu/sound.cpp
@@ -835,7 +835,7 @@ sound_manager::sound_manager(running_machine &machine)
 #endif
 
 	// register callbacks
-	machine.configuration().config_register("mixer", config_saveload_delegate(&sound_manager::config_load, this), config_saveload_delegate(&sound_manager::config_save, this));
+	machine.configuration().config_register("mixer", config_load_delegate(&sound_manager::config_load, this), config_save_delegate(&sound_manager::config_save, this));
 	machine.add_notifier(MACHINE_NOTIFY_PAUSE, machine_notify_delegate(&sound_manager::pause, this));
 	machine.add_notifier(MACHINE_NOTIFY_RESUME, machine_notify_delegate(&sound_manager::resume, this));
 	machine.add_notifier(MACHINE_NOTIFY_RESET, machine_notify_delegate(&sound_manager::reset, this));
@@ -988,10 +988,10 @@ void sound_manager::resume()
 //  configuration file
 //-------------------------------------------------
 
-void sound_manager::config_load(config_type cfg_type, xml_data_node *parentnode)
+void sound_manager::config_load(config_type cfg_type, util::xml::data_node const *parentnode)
 {
 	// we only care about game files
-	if (cfg_type != config_type::CONFIG_TYPE_GAME)
+	if (cfg_type != config_type::GAME)
 		return;
 
 	// might not have any data
@@ -999,7 +999,7 @@ void sound_manager::config_load(config_type cfg_type, xml_data_node *parentnode)
 		return;
 
 	// iterate over channel nodes
-	for (xml_data_node const *channelnode = parentnode->get_child("channel"); channelnode != nullptr; channelnode = channelnode->get_next_sibling("channel"))
+	for (util::xml::data_node const *channelnode = parentnode->get_child("channel"); channelnode != nullptr; channelnode = channelnode->get_next_sibling("channel"))
 	{
 		mixer_input info;
 		if (indexed_mixer_input(channelnode->get_attribute_int("index", -1), info))
@@ -1018,10 +1018,10 @@ void sound_manager::config_load(config_type cfg_type, xml_data_node *parentnode)
 //  file
 //-------------------------------------------------
 
-void sound_manager::config_save(config_type cfg_type, xml_data_node *parentnode)
+void sound_manager::config_save(config_type cfg_type, util::xml::data_node *parentnode)
 {
 	// we only care about game files
-	if (cfg_type != config_type::CONFIG_TYPE_GAME)
+	if (cfg_type != config_type::GAME)
 		return;
 
 	// iterate over mixer channels
@@ -1035,7 +1035,7 @@ void sound_manager::config_save(config_type cfg_type, xml_data_node *parentnode)
 
 			if (newvol != 1.0f)
 			{
-				xml_data_node *const channelnode = parentnode->add_child("channel", nullptr);
+				util::xml::data_node *const channelnode = parentnode->add_child("channel", nullptr);
 				if (channelnode != nullptr)
 				{
 					channelnode->set_attribute_int("index", mixernum);
diff --git a/src/emu/sound.h b/src/emu/sound.h
index d9b9a61..8cb4c72 100644
--- a/src/emu/sound.h
+++ b/src/emu/sound.h
@@ -223,8 +223,8 @@ private:
 	void reset();
 	void pause();
 	void resume();
-	void config_load(config_type cfg_type, xml_data_node *parentnode);
-	void config_save(config_type cfg_type, xml_data_node *parentnode);
+	void config_load(config_type cfg_type, util::xml::data_node const *parentnode);
+	void config_save(config_type cfg_type, util::xml::data_node *parentnode);
 
 	void update(void *ptr = nullptr, s32 param = 0);
 
diff --git a/src/emu/ui/cmddata.h b/src/emu/ui/cmddata.h
index 14c09c7..675195f 100644
--- a/src/emu/ui/cmddata.h
+++ b/src/emu/ui/cmddata.h
@@ -50,7 +50,7 @@ enum
 #define COMMAND_CONVERT_TEXT    '@'
 
 // Defined Game Command Font Color Array
-static rgb_t color_table[] =
+static rgb_t const color_table[] =
 {
 	0,                   // dummy
 	BUTTON_COLOR_RED,    // BTN_A
@@ -147,19 +147,19 @@ static rgb_t color_table[] =
 
 struct fix_command_t
 {
-	unsigned char   glyph_char;
-	const int       glyph_code;
+	char        glyph_char;
+	unsigned    glyph_code;
 };
 
 
 struct fix_strings_t
 {
-	const char  *glyph_str;
-	const int   glyph_code;
-	int         glyph_str_len;
+	char const  *glyph_str;
+	int const   glyph_code;
+	unsigned    glyph_str_len;
 };
 
-static fix_command_t default_text[] =
+static fix_command_t const default_text[] =
 {
 	// Alphabetic Buttons (NeoGeo): A~D,H,Z
 	{ 'A', 1 },     // BTN_A
@@ -248,7 +248,7 @@ static fix_command_t default_text[] =
 	{ 0, 0 }    // end of array
 };
 
-static fix_command_t expand_text[] =
+static fix_command_t const expand_text[] =
 {
 	// Alphabetic Buttons (NeoGeo): S (Slash Button)
 	{ 's', 19 },    // BTN_S
@@ -289,114 +289,114 @@ static fix_command_t expand_text[] =
 static fix_strings_t convert_text[] =
 {
 	// Alphabetic Buttons: A~Z
-	{ "A-button",  1 }, // BTN_A
-	{ "B-button",  2 }, // BTN_B
-	{ "C-button",  3 }, // BTN_C
-	{ "D-button",  4 }, // BTN_D
-	{ "E-button",  5 }, // BTN_E
-	{ "F-button",  6 }, // BTN_F
-	{ "G-button",  7 }, // BTN_G
-	{ "H-button",  8 }, // BTN_H
-	{ "I-button",  9 }, // BTN_I
-	{ "J-button", 10 }, // BTN_J
-	{ "K-button", 11 }, // BTN_K
-	{ "L-button", 12 }, // BTN_L
-	{ "M-button", 13 }, // BTN_M
-	{ "N-button", 14 }, // BTN_N
-	{ "O-button", 15 }, // BTN_O
-	{ "P-button", 16 }, // BTN_P
-	{ "Q-button", 17 }, // BTN_Q
-	{ "R-button", 18 }, // BTN_R
-	{ "S-button", 19 }, // BTN_S
-	{ "T-button", 20 }, // BTN_T
-	{ "U-button", 21 }, // BTN_U
-	{ "V-button", 22 }, // BTN_V
-	{ "W-button", 23 }, // BTN_W
-	{ "X-button", 24 }, // BTN_X
-	{ "Y-button", 25 }, // BTN_Y
-	{ "Z-button", 26 }, // BTN_Z
+	{ "A-button",  1, 0 }, // BTN_A
+	{ "B-button",  2, 0 }, // BTN_B
+	{ "C-button",  3, 0 }, // BTN_C
+	{ "D-button",  4, 0 }, // BTN_D
+	{ "E-button",  5, 0 }, // BTN_E
+	{ "F-button",  6, 0 }, // BTN_F
+	{ "G-button",  7, 0 }, // BTN_G
+	{ "H-button",  8, 0 }, // BTN_H
+	{ "I-button",  9, 0 }, // BTN_I
+	{ "J-button", 10, 0 }, // BTN_J
+	{ "K-button", 11, 0 }, // BTN_K
+	{ "L-button", 12, 0 }, // BTN_L
+	{ "M-button", 13, 0 }, // BTN_M
+	{ "N-button", 14, 0 }, // BTN_N
+	{ "O-button", 15, 0 }, // BTN_O
+	{ "P-button", 16, 0 }, // BTN_P
+	{ "Q-button", 17, 0 }, // BTN_Q
+	{ "R-button", 18, 0 }, // BTN_R
+	{ "S-button", 19, 0 }, // BTN_S
+	{ "T-button", 20, 0 }, // BTN_T
+	{ "U-button", 21, 0 }, // BTN_U
+	{ "V-button", 22, 0 }, // BTN_V
+	{ "W-button", 23, 0 }, // BTN_W
+	{ "X-button", 24, 0 }, // BTN_X
+	{ "Y-button", 25, 0 }, // BTN_Y
+	{ "Z-button", 26, 0 }, // BTN_Z
 	// Special Moves and Buttons
-	{ "decrease", 37 }, // BTN_DEC
-	{ "increase", 38 }, // BTN_INC
-	{ "BALL",    45 },  // Joystick Ball
-	{ "start",  51 },   // BTN_START
-	{ "select",   52 }, // BTN_SELECT
-	{ "punch",  53 },   // BTN_PUNCH
-	{ "kick",    54 },  // BTN_KICK
-	{ "guard",  55 },   // BTN_GUARD
-	{ "L-punch",  57 }, // Light Punch
-	{ "M-punch",  58 }, // Middle Punch
-	{ "S-punch",  59 }, // Strong Punch
-	{ "L-kick",   60 }, // Light Kick
-	{ "M-kick",   61 }, // Middle Kick
-	{ "S-kick",   62 }, // Strong Kick
-	{ "3-kick",   63 }, // 3 Kick
-	{ "3-punch",  64 }, // 3 Punch
-	{ "2-kick",   65 }, // 2 Kick
-	{ "2-punch",  66 }, // 2 Pick
+	{ "decrease", 37, 0 }, // BTN_DEC
+	{ "increase", 38, 0 }, // BTN_INC
+	{ "BALL",     45, 0 }, // Joystick Ball
+	{ "start",    51, 0 }, // BTN_START
+	{ "select",   52, 0 }, // BTN_SELECT
+	{ "punch",    53, 0 }, // BTN_PUNCH
+	{ "kick",     54, 0 }, // BTN_KICK
+	{ "guard",    55, 0 }, // BTN_GUARD
+	{ "L-punch",  57, 0 }, // Light Punch
+	{ "M-punch",  58, 0 }, // Middle Punch
+	{ "S-punch",  59, 0 }, // Strong Punch
+	{ "L-kick",   60, 0 }, // Light Kick
+	{ "M-kick",   61, 0 }, // Middle Kick
+	{ "S-kick",   62, 0 }, // Strong Kick
+	{ "3-kick",   63, 0 }, // 3 Kick
+	{ "3-punch",  64, 0 }, // 3 Punch
+	{ "2-kick",   65, 0 }, // 2 Kick
+	{ "2-punch",  66, 0 }, // 2 Pick
 	// Custom Buttons and Cursor Buttons
-	{ "custom1",  67 }, // CUSTOM_1
-	{ "custom2",  68 }, // CUSTOM_2
-	{ "custom3",  69 }, // CUSTOM_3
-	{ "custom4",  70 }, // CUSTOM_4
-	{ "custom5",  71 }, // CUSTOM_5
-	{ "custom6",  72 }, // CUSTOM_6
-	{ "custom7",  73 }, // CUSTOM_7
-	{ "custom8",  74 }, // CUSTOM_8
-	{ "up",    75 },    // (Cursor Up)
-	{ "down",    76 },  // (Cursor Down)
-	{ "left",    77 },  // (Cursor Left)
-	{ "right",  78 },   // (Cursor Right)
+	{ "custom1",  67, 0 }, // CUSTOM_1
+	{ "custom2",  68, 0 }, // CUSTOM_2
+	{ "custom3",  69, 0 }, // CUSTOM_3
+	{ "custom4",  70, 0 }, // CUSTOM_4
+	{ "custom5",  71, 0 }, // CUSTOM_5
+	{ "custom6",  72, 0 }, // CUSTOM_6
+	{ "custom7",  73, 0 }, // CUSTOM_7
+	{ "custom8",  74, 0 }, // CUSTOM_8
+	{ "up",       75, 0 }, // (Cursor Up)
+	{ "down",     76, 0 }, // (Cursor Down)
+	{ "left",     77, 0 }, // (Cursor Left)
+	{ "right",    78, 0 }, // (Cursor Right)
 	// Player Lever
-	{ "lever",  79 },   // Non Player Lever
-	{ "nplayer",  80 }, // Gray Color Lever
-	{ "1player",  81 }, // 1 Player Lever
-	{ "2player",  82 }, // 2 Player Lever
-	{ "3player",  83 }, // 3 Player Lever
-	{ "4player",  84 }, // 4 Player Lever
-	{ "5player",  85 }, // 5 Player Lever
-	{ "6player",  86 }, // 6 Player Lever
-	{ "7player",  87 }, // 7 Player Lever
-	{ "8player",  88 }, // 8 Player Lever
+	{ "lever",    79, 0 }, // Non Player Lever
+	{ "nplayer",  80, 0 }, // Gray Color Lever
+	{ "1player",  81, 0 }, // 1 Player Lever
+	{ "2player",  82, 0 }, // 2 Player Lever
+	{ "3player",  83, 0 }, // 3 Player Lever
+	{ "4player",  84, 0 }, // 4 Player Lever
+	{ "5player",  85, 0 }, // 5 Player Lever
+	{ "6player",  86, 0 }, // 6 Player Lever
+	{ "7player",  87, 0 }, // 7 Player Lever
+	{ "8player",  88, 0 }, // 8 Player Lever
 	// Composition of Arrow Directions
-	{ "-->",      90 }, // Arrow
-	{ "==>",      91 }, // Continue Arrow
-	{ "hcb",     100 }, // Half Circle Back
-	{ "huf",     101 }, // Half Circle Front Up
-	{ "hcf",     102 }, // Half Circle Front
-	{ "hub",     103 }, // Half Circle Back Up
-	{ "qfd",     104 }, // 1/4 Cir For 2 Down
-	{ "qdb",     105 }, // 1/4 Cir Down 2 Back
-	{ "qbu",     106 }, // 1/4 Cir Back 2 Up
-	{ "quf",     107 }, // 1/4 Cir Up 2 For
-	{ "qbd",     108 }, // 1/4 Cir Back 2 Down
-	{ "qdf",     109 }, // 1/4 Cir Down 2 For
-	{ "qfu",     110 }, // 1/4 Cir For 2 Up
-	{ "qub",     111 }, // 1/4 Cir Up 2 Back
-	{ "fdf",     112 }, // Full Clock Forward
-	{ "fub",     113 }, // Full Clock Back
-	{ "fuf",     114 }, // Full Count Forward
-	{ "fdb",     115 }, // Full Count Back
-	{ "xff",     116 }, // 2x Forward
-	{ "xbb",     117 }, // 2x Back
-	{ "dsf",     118 }, // Dragon Screw Forward
-	{ "dsb",     119 }, // Dragon Screw Back
+	{ "-->",      90, 0 }, // Arrow
+	{ "==>",      91, 0 }, // Continue Arrow
+	{ "hcb",     100, 0 }, // Half Circle Back
+	{ "huf",     101, 0 }, // Half Circle Front Up
+	{ "hcf",     102, 0 }, // Half Circle Front
+	{ "hub",     103, 0 }, // Half Circle Back Up
+	{ "qfd",     104, 0 }, // 1/4 Cir For 2 Down
+	{ "qdb",     105, 0 }, // 1/4 Cir Down 2 Back
+	{ "qbu",     106, 0 }, // 1/4 Cir Back 2 Up
+	{ "quf",     107, 0 }, // 1/4 Cir Up 2 For
+	{ "qbd",     108, 0 }, // 1/4 Cir Back 2 Down
+	{ "qdf",     109, 0 }, // 1/4 Cir Down 2 For
+	{ "qfu",     110, 0 }, // 1/4 Cir For 2 Up
+	{ "qub",     111, 0 }, // 1/4 Cir Up 2 Back
+	{ "fdf",     112, 0 }, // Full Clock Forward
+	{ "fub",     113, 0 }, // Full Clock Back
+	{ "fuf",     114, 0 }, // Full Count Forward
+	{ "fdb",     115, 0 }, // Full Count Back
+	{ "xff",     116, 0 }, // 2x Forward
+	{ "xbb",     117, 0 }, // 2x Back
+	{ "dsf",     118, 0 }, // Dragon Screw Forward
+	{ "dsb",     119, 0 }, // Dragon Screw Back
 	// Big letter Text
-	{ "AIR",     121 }, // AIR
-	{ "DIR",     122 }, // DIR
-	{ "MAX",     123 }, // MAX
-	{ "TAP",     124 }, // TAP
+	{ "AIR",     121, 0 }, // AIR
+	{ "DIR",     122, 0 }, // DIR
+	{ "MAX",     123, 0 }, // MAX
+	{ "TAP",     124, 0 }, // TAP
 	// Condition of Positions
-	{ "jump",   125 },  // Jump
-	{ "hold",   126 },  // Hold
-	{ "air",     127 }, // Air
-	{ "sit",     128 }, // Squatting
-	{ "close",   129 }, // Close
-	{ "away",   130 },  // Away
-	{ "charge",  131 }, // Charge
-	{ "tap",     132 }, // Serious Tap
-	{ "button",  133 }, // Any Button
-	{ nullptr, 0 }    // end of array
+	{ "jump",    125, 0 }, // Jump
+	{ "hold",    126, 0 }, // Hold
+	{ "air",     127, 0 }, // Air
+	{ "sit",     128, 0 }, // Squatting
+	{ "close",   129, 0 }, // Close
+	{ "away",    130, 0 }, // Away
+	{ "charge",  131, 0 }, // Charge
+	{ "tap",     132, 0 }, // Serious Tap
+	{ "button",  133, 0 }, // Any Button
+	{ nullptr,     0, 0 }  // end of array
 };
 
 #endif /* __UI_CMDDATA_H__ */
diff --git a/src/emu/ui/cmdrender.h b/src/emu/ui/cmdrender.h
deleted file mode 100644
index 905b681..0000000
--- a/src/emu/ui/cmdrender.h
+++ /dev/null
@@ -1,150 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Maurizio Petrarota
-/***************************************************************************
-
-    ui/cmdrender.h
-
-    UI command render fonts.
-
-***************************************************************************/
-
-#include "ui/uicmd14.fh"
-#include "ui/cmddata.h"
-
-void convert_command_glyph(std::string &str)
-{
-	int j;
-	int len = str.length();
-	int buflen = (len + 2) * 2;
-	char *d = global_alloc_array(char, buflen);
-
-	for (int i = j = 0; i < len;)
-	{
-		fix_command_t *fixcmd = nullptr;
-		char32_t uchar;
-		int ucharcount = uchar_from_utf8(&uchar, str.substr(i).c_str(), len - i);
-		if (ucharcount == -1)
-			break;
-		else if (ucharcount != 1)
-			goto process_next;
-		else if (str[i] == '\n')
-			uchar = '\n';
-		else if (str[i] == COMMAND_CONVERT_TEXT)
-		{
-			if (str[i] == str[i + 1])
-				++i;
-			else
-			{
-				fix_strings_t *fixtext = convert_text;
-				for (; fixtext->glyph_code; ++fixtext)
-				{
-					if (!fixtext->glyph_str_len)
-						fixtext->glyph_str_len = strlen(fixtext->glyph_str);
-
-					if (strncmp(fixtext->glyph_str, str.substr(i + 1).c_str(), fixtext->glyph_str_len) == 0)
-					{
-						uchar = fixtext->glyph_code + COMMAND_UNICODE;
-						i += strlen(fixtext->glyph_str);
-						break;
-					}
-				}
-			}
-		}
-		else if (str[i] == COMMAND_DEFAULT_TEXT)
-			fixcmd = default_text;
-		else if (str[i] == COMMAND_EXPAND_TEXT)
-			fixcmd = expand_text;
-
-		if (fixcmd)
-		{
-			if (str[i] == str[i + 1])
-				i++;
-			else
-			{
-				for (; fixcmd->glyph_code; ++fixcmd)
-					if (str[i + 1] == fixcmd->glyph_char)
-					{
-						uchar = fixcmd->glyph_code + COMMAND_UNICODE;
-						++i;
-						break;
-					}
-			}
-		}
-process_next:
-		i += ucharcount;
-		ucharcount = utf8_from_uchar(d + j, buflen - j - 1, uchar);
-		if (ucharcount == -1)
-			break;
-		j += ucharcount;
-	}
-	d[j] = '\0';
-	str = d;
-	global_free_array(d);
-}
-
-void render_font::render_font_command_glyph()
-{
-	emu_file ramfile(OPEN_FLAG_READ);
-
-	if (ramfile.open_ram(font_uicmd14, sizeof(font_uicmd14)) == osd_file::error::NONE)
-		load_cached_cmd(ramfile, 0);
-}
-
-bool render_font::load_cached_cmd(emu_file &file, u32 hash)
-{
-	u64 filesize = file.size();
-	u8 header[CACHED_HEADER_SIZE];
-	u32 bytes_read = file.read(header, CACHED_HEADER_SIZE);
-
-	if (bytes_read != CACHED_HEADER_SIZE)
-		return false;
-
-	if (header[0] != 'f' || header[1] != 'o' || header[2] != 'n' || header[3] != 't')
-		return false;
-	if (header[4] != u8(hash >> 24) || header[5] != u8(hash >> 16) || header[6] != u8(hash >> 8) || header[7] != u8(hash))
-		return false;
-	m_height_cmd = (header[8] << 8) | header[9];
-	m_yoffs_cmd = s16((header[10] << 8) | header[11]);
-	u32 numchars = (header[12] << 24) | (header[13] << 16) | (header[14] << 8) | header[15];
-	if (filesize - CACHED_HEADER_SIZE < numchars * CACHED_CHAR_SIZE)
-		return false;
-
-	m_rawdata_cmd.resize(filesize - CACHED_HEADER_SIZE);
-	bytes_read = file.read(&m_rawdata_cmd[0], filesize - CACHED_HEADER_SIZE);
-	if (bytes_read != filesize - CACHED_HEADER_SIZE)
-	{
-		m_rawdata_cmd.clear();
-		return false;
-	}
-
-	u64 offset = numchars * CACHED_CHAR_SIZE;
-	for (int chindex = 0; chindex < numchars; chindex++)
-	{
-		const u8 *info = reinterpret_cast<u8 *>(&m_rawdata_cmd[chindex * CACHED_CHAR_SIZE]);
-		int chnum = (info[0] << 8) | info[1];
-
-		if (!m_glyphs_cmd[chnum / 256])
-			m_glyphs_cmd[chnum / 256] = new glyph[256];
-
-		glyph &gl = m_glyphs_cmd[chnum / 256][chnum % 256];
-
-		if (chnum >= COMMAND_UNICODE && chnum < COMMAND_UNICODE + COLOR_BUTTONS)
-			gl.color = color_table[chnum - COMMAND_UNICODE];
-
-		gl.width = (info[2] << 8) | info[3];
-		gl.xoffs = s16((info[4] << 8) | info[5]);
-		gl.yoffs = s16((info[6] << 8) | info[7]);
-		gl.bmwidth = (info[8] << 8) | info[9];
-		gl.bmheight = (info[10] << 8) | info[11];
-		gl.rawdata = &m_rawdata_cmd[offset];
-
-		offset += (gl.bmwidth * gl.bmheight + 7) / 8;
-		if (offset > filesize - CACHED_HEADER_SIZE)
-		{
-			m_rawdata_cmd.clear();
-			return false;
-		}
-	}
-
-	return true;
-}
diff --git a/src/emu/uiinput.cpp b/src/emu/uiinput.cpp
index 952a5b3..9123a6a 100644
--- a/src/emu/uiinput.cpp
+++ b/src/emu/uiinput.cpp
@@ -263,7 +263,14 @@ g_profiler.start(PROFILER_INPUT);
 
 		/* if this is an autorepeat case, set a 1x delay and leave pressed = 1 */
 		else if (speed > 0 && (osd_ticks() + tps - m_next_repeat[code]) >= tps)
-			m_next_repeat[code] += 1 * speed * tps / 60;
+		{
+			// In the autorepeatcase, we need to double check the key is still pressed
+			// as there can be a delay between the key polling and our processing of the event
+			m_seqpressed[code] = machine().ioport().type_pressed(ioport_type(code));
+			pressed = (m_seqpressed[code] == SEQ_PRESSED_TRUE);
+			if (pressed)
+				m_next_repeat[code] += 1 * speed * tps / 60;
+		}
 
 		/* otherwise, reset pressed = 0 */
 		else
diff --git a/src/frontend/mame/cheat.cpp b/src/frontend/mame/cheat.cpp
index 3c2b2e1..2c758ed 100644
--- a/src/frontend/mame/cheat.cpp
+++ b/src/frontend/mame/cheat.cpp
@@ -108,16 +108,16 @@ inline std::string number_and_format::format() const
 	switch (m_format)
 	{
 	default:
-	case xml_data_node::int_format::DECIMAL:
+	case util::xml::data_node::int_format::DECIMAL:
 		return string_format("%d", uint32_t(m_value));
 
-	case xml_data_node::int_format::DECIMAL_HASH:
+	case util::xml::data_node::int_format::DECIMAL_HASH:
 		return string_format("#%d", uint32_t(m_value));
 
-	case xml_data_node::int_format::HEX_DOLLAR:
+	case util::xml::data_node::int_format::HEX_DOLLAR:
 		return string_format("$%X", uint32_t(m_value));
 
-	case xml_data_node::int_format::HEX_C:
+	case util::xml::data_node::int_format::HEX_C:
 		return string_format("0x%X", uint32_t(m_value));
 	}
 }
@@ -132,7 +132,7 @@ inline std::string number_and_format::format() const
 //  cheat_parameter - constructor
 //-------------------------------------------------
 
-cheat_parameter::cheat_parameter(cheat_manager &manager, symbol_table &symbols, const char *filename, xml_data_node const &paramnode)
+cheat_parameter::cheat_parameter(cheat_manager &manager, symbol_table &symbols, const char *filename, util::xml::data_node const &paramnode)
 	: m_value(0)
 {
 	// read the core attributes
@@ -141,7 +141,7 @@ cheat_parameter::cheat_parameter(cheat_manager &manager, symbol_table &symbols,
 	m_stepval = number_and_format(paramnode.get_attribute_int("step", 1), paramnode.get_attribute_int_format("step"));
 
 	// iterate over items
-	for (xml_data_node const *itemnode = paramnode.get_child("item"); itemnode != nullptr; itemnode = itemnode->get_next_sibling("item"))
+	for (util::xml::data_node const *itemnode = paramnode.get_child("item"); itemnode != nullptr; itemnode = itemnode->get_next_sibling("item"))
 	{
 		// check for nullptr text
 		if (itemnode->get_value() == nullptr || itemnode->get_value()[0] == 0)
@@ -153,7 +153,7 @@ cheat_parameter::cheat_parameter(cheat_manager &manager, symbol_table &symbols,
 
 		// extract the parameters
 		uint64_t const value = itemnode->get_attribute_int("value", 0);
-		xml_data_node::int_format const format = itemnode->get_attribute_int_format("value");
+		util::xml::data_node::int_format const format = itemnode->get_attribute_int_format("value");
 
 		// allocate and append a new item
 		auto curitem = std::make_unique<item>(itemnode->get_value(), value, format);
@@ -317,7 +317,7 @@ bool cheat_parameter::set_next_state()
 //  cheat_script - constructor
 //-------------------------------------------------
 
-cheat_script::cheat_script(cheat_manager &manager, symbol_table &symbols, const char *filename, xml_data_node const &scriptnode)
+cheat_script::cheat_script(cheat_manager &manager, symbol_table &symbols, const char *filename, util::xml::data_node const &scriptnode)
 	: m_state(SCRIPT_STATE_RUN)
 {
 	// read the core attributes
@@ -332,7 +332,7 @@ cheat_script::cheat_script(cheat_manager &manager, symbol_table &symbols, const
 		throw emu_fatalerror("%s.xml(%d): invalid script state '%s'\n", filename, scriptnode.line, state);
 
 	// iterate over nodes within the script
-	for (xml_data_node const *entrynode = scriptnode.get_first_child(); entrynode != nullptr; entrynode = entrynode->get_next_sibling())
+	for (util::xml::data_node const *entrynode = scriptnode.get_first_child(); entrynode != nullptr; entrynode = entrynode->get_next_sibling())
 	{
 		// handle action nodes
 		if (strcmp(entrynode->get_name(), "action") == 0)
@@ -399,7 +399,7 @@ void cheat_script::save(emu_file &cheatfile) const
 //  script_entry - constructor
 //-------------------------------------------------
 
-cheat_script::script_entry::script_entry(cheat_manager &manager, symbol_table &symbols, const char *filename, xml_data_node const &entrynode, bool isaction)
+cheat_script::script_entry::script_entry(cheat_manager &manager, symbol_table &symbols, const char *filename, util::xml::data_node const &entrynode, bool isaction)
 	: m_condition(&symbols),
 		m_expression(&symbols)
 {
@@ -442,7 +442,7 @@ cheat_script::script_entry::script_entry(cheat_manager &manager, symbol_table &s
 
 			// then parse arguments
 			int totalargs = 0;
-			for (xml_data_node const *argnode = entrynode.get_child("argument"); argnode != nullptr; argnode = argnode->get_next_sibling("argument"))
+			for (util::xml::data_node const *argnode = entrynode.get_child("argument"); argnode != nullptr; argnode = argnode->get_next_sibling("argument"))
 			{
 				auto curarg = std::make_unique<output_argument>(manager, symbols, filename, *argnode);
 				// verify we didn't overrun the argument count
@@ -608,7 +608,7 @@ void cheat_script::script_entry::validate_format(const char *filename, int line)
 //  output_argument - constructor
 //-------------------------------------------------
 
-cheat_script::script_entry::output_argument::output_argument(cheat_manager &manager, symbol_table &symbols, const char *filename, xml_data_node const &argnode)
+cheat_script::script_entry::output_argument::output_argument(cheat_manager &manager, symbol_table &symbols, const char *filename, util::xml::data_node const &argnode)
 	: m_expression(&symbols),
 		m_count(0)
 {
@@ -676,7 +676,7 @@ void cheat_script::script_entry::output_argument::save(emu_file &cheatfile) cons
 //  cheat_entry - constructor
 //-------------------------------------------------
 
-cheat_entry::cheat_entry(cheat_manager &manager, symbol_table &globaltable, const char *filename, xml_data_node const &cheatnode)
+cheat_entry::cheat_entry(cheat_manager &manager, symbol_table &globaltable, const char *filename, util::xml::data_node const &cheatnode)
 	: m_manager(manager)
 	, m_symbols(&manager.machine(), &globaltable)
 	, m_state(SCRIPT_STATE_OFF)
@@ -707,7 +707,7 @@ cheat_entry::cheat_entry(cheat_manager &manager, symbol_table &globaltable, cons
 		}
 
 		// read the first comment node
-		xml_data_node const *commentnode = cheatnode.get_child("comment");
+		util::xml::data_node const *commentnode = cheatnode.get_child("comment");
 		if (commentnode != nullptr)
 		{
 			// set the value if not nullptr
@@ -721,7 +721,7 @@ cheat_entry::cheat_entry(cheat_manager &manager, symbol_table &globaltable, cons
 		}
 
 		// read the first parameter node
-		xml_data_node const *paramnode = cheatnode.get_child("parameter");
+		util::xml::data_node const *paramnode = cheatnode.get_child("parameter");
 		if (paramnode != nullptr)
 		{
 			// load this parameter
@@ -734,7 +734,7 @@ cheat_entry::cheat_entry(cheat_manager &manager, symbol_table &globaltable, cons
 		}
 
 		// read the script nodes
-		for (xml_data_node const *scriptnode = cheatnode.get_child("script"); scriptnode != nullptr; scriptnode = scriptnode->get_next_sibling("script"))
+		for (util::xml::data_node const *scriptnode = cheatnode.get_child("script"); scriptnode != nullptr; scriptnode = scriptnode->get_next_sibling("script"))
 		{
 			// load this entry
 			auto curscript = global_alloc(cheat_script(manager, m_symbols, filename, *scriptnode));
@@ -1397,17 +1397,17 @@ void cheat_manager::load_cheats(const char *filename)
 			osd_printf_verbose("Loading cheats file from %s\n", cheatfile.fullpath());
 
 			// read the XML file into internal data structures
-			xml_parse_options options = { nullptr };
-			xml_parse_error error;
+			util::xml::parse_options options = { nullptr };
+			util::xml::parse_error error;
 			options.error = &error;
-			std::unique_ptr<xml_data_node, void (*)(xml_data_node *)> rootnode(xml_data_node::file_read(cheatfile, &options), [] (xml_data_node *node) { node->file_free(); });
+			std::unique_ptr<util::xml::data_node, void (*)(util::xml::data_node *)> rootnode(util::xml::data_node::file_read(cheatfile, &options), [] (util::xml::data_node *node) { node->file_free(); });
 
 			// if unable to parse the file, just bail
 			if (rootnode == nullptr)
 				throw emu_fatalerror("%s.xml(%d): error parsing XML (%s)\n", filename, error.error_line, error.error_message);
 
 			// find the layout node
-			xml_data_node *mamecheatnode = rootnode->get_child("mamecheat");
+			util::xml::data_node const *const mamecheatnode = rootnode->get_child("mamecheat");
 			if (mamecheatnode == nullptr)
 				throw emu_fatalerror("%s.xml: missing mamecheatnode node", filename);
 
@@ -1417,7 +1417,7 @@ void cheat_manager::load_cheats(const char *filename)
 				throw emu_fatalerror("%s.xml(%d): Invalid cheat XML file: unsupported version", filename, mamecheatnode->line);
 
 			// parse all the elements
-			for (xml_data_node const *cheatnode = mamecheatnode->get_child("cheat"); cheatnode != nullptr; cheatnode = cheatnode->get_next_sibling("cheat"))
+			for (util::xml::data_node const *cheatnode = mamecheatnode->get_child("cheat"); cheatnode != nullptr; cheatnode = cheatnode->get_next_sibling("cheat"))
 			{
 				// load this entry
 				auto curcheat = std::make_unique<cheat_entry>(*this, m_symtable, filename, *cheatnode);
diff --git a/src/frontend/mame/cheat.h b/src/frontend/mame/cheat.h
index bc983c1..eaba365 100644
--- a/src/frontend/mame/cheat.h
+++ b/src/frontend/mame/cheat.h
@@ -50,7 +50,7 @@ class number_and_format
 {
 public:
 	// construction/destruction
-	number_and_format(uint64_t value = 0, xml_data_node::int_format format = xml_data_node::int_format::DECIMAL)
+	number_and_format(uint64_t value = 0, util::xml::data_node::int_format format = util::xml::data_node::int_format::DECIMAL)
 		: m_value(value)
 		, m_format(format)
 	{
@@ -65,8 +65,8 @@ public:
 
 private:
 	// internal state
-	uint64_t                    m_value;
-	xml_data_node::int_format   m_format;
+	uint64_t                            m_value;
+	util::xml::data_node::int_format    m_format;
 };
 
 
@@ -77,7 +77,7 @@ class cheat_parameter
 {
 public:
 	// construction/destruction
-	cheat_parameter(cheat_manager &manager, symbol_table &symbols, const char *filename, xml_data_node const &paramnode);
+	cheat_parameter(cheat_manager &manager, symbol_table &symbols, const char *filename, util::xml::data_node const &paramnode);
 
 	// queries
 	const char *text();
@@ -99,7 +99,7 @@ private:
 	{
 	public:
 		// construction/destruction
-		item(const char *text, uint64_t value, xml_data_node::int_format valformat)
+		item(const char *text, uint64_t value, util::xml::data_node::int_format valformat)
 			: m_text(text)
 			, m_value(value, valformat)
 		{ }
@@ -131,7 +131,7 @@ class cheat_script
 {
 public:
 	// construction/destruction
-	cheat_script(cheat_manager &manager, symbol_table &symbols, const char *filename, xml_data_node const &scriptnode);
+	cheat_script(cheat_manager &manager, symbol_table &symbols, const char *filename, util::xml::data_node const &scriptnode);
 
 	// getters
 	script_state state() const { return m_state; }
@@ -146,7 +146,7 @@ private:
 	{
 	public:
 		// construction/destruction
-		script_entry(cheat_manager &manager, symbol_table &symbols, const char *filename, xml_data_node const &entrynode, bool isaction);
+		script_entry(cheat_manager &manager, symbol_table &symbols, const char *filename, util::xml::data_node const &entrynode, bool isaction);
 
 		// actions
 		void execute(cheat_manager &manager, uint64_t &argindex);
@@ -158,7 +158,7 @@ private:
 		{
 		public:
 			// construction/destruction
-			output_argument(cheat_manager &manager, symbol_table &symbols, const char *filename, xml_data_node const &argnode);
+			output_argument(cheat_manager &manager, symbol_table &symbols, const char *filename, util::xml::data_node const &argnode);
 
 			// getters
 			int count() const { return m_count; }
@@ -201,7 +201,7 @@ class cheat_entry
 {
 public:
 	// construction/destruction
-	cheat_entry(cheat_manager &manager, symbol_table &globaltable, const char *filename, xml_data_node const &cheatnode);
+	cheat_entry(cheat_manager &manager, symbol_table &globaltable, const char *filename, util::xml::data_node const &cheatnode);
 	~cheat_entry();
 
 	// getters
diff --git a/src/frontend/mame/clifront.cpp b/src/frontend/mame/clifront.cpp
index 40775af..ff7e371 100644
--- a/src/frontend/mame/clifront.cpp
+++ b/src/frontend/mame/clifront.cpp
@@ -1101,7 +1101,7 @@ void cli_frontend::verifysamples(const char *gamename)
 
 void cli_frontend::output_single_softlist(FILE *out, software_list_device &swlistdev)
 {
-	fprintf(out, "\t<softwarelist name=\"%s\" description=\"%s\">\n", swlistdev.list_name().c_str(), xml_normalize_string(swlistdev.description().c_str()));
+	fprintf(out, "\t<softwarelist name=\"%s\" description=\"%s\">\n", swlistdev.list_name().c_str(), util::xml::normalize_string(swlistdev.description().c_str()));
 	for (const software_info &swinfo : swlistdev.get_info())
 	{
 		fprintf(out, "\t\t<software name=\"%s\"", swinfo.shortname().c_str());
@@ -1112,12 +1112,12 @@ void cli_frontend::output_single_softlist(FILE *out, software_list_device &swlis
 		if (swinfo.supported() == SOFTWARE_SUPPORTED_NO)
 			fprintf(out, " supported=\"no\"");
 		fprintf(out, ">\n" );
-		fprintf(out, "\t\t\t<description>%s</description>\n", xml_normalize_string(swinfo.longname().c_str()));
-		fprintf(out, "\t\t\t<year>%s</year>\n", xml_normalize_string(swinfo.year().c_str()));
-		fprintf(out, "\t\t\t<publisher>%s</publisher>\n", xml_normalize_string(swinfo.publisher().c_str()));
+		fprintf(out, "\t\t\t<description>%s</description>\n", util::xml::normalize_string(swinfo.longname().c_str()));
+		fprintf(out, "\t\t\t<year>%s</year>\n", util::xml::normalize_string(swinfo.year().c_str()));
+		fprintf(out, "\t\t\t<publisher>%s</publisher>\n", util::xml::normalize_string(swinfo.publisher().c_str()));
 
 		for (const feature_list_item &flist : swinfo.other_info())
-			fprintf( out, "\t\t\t<info name=\"%s\" value=\"%s\"/>\n", flist.name().c_str(), xml_normalize_string( flist.value().c_str()) );
+			fprintf( out, "\t\t\t<info name=\"%s\" value=\"%s\"/>\n", flist.name().c_str(), util::xml::normalize_string( flist.value().c_str()) );
 
 		for (const software_part &part : swinfo.parts())
 		{
@@ -1128,7 +1128,7 @@ void cli_frontend::output_single_softlist(FILE *out, software_list_device &swlis
 			fprintf(out, ">\n");
 
 			for (const feature_list_item &flist : part.featurelist())
-				fprintf(out, "\t\t\t\t<feature name=\"%s\" value=\"%s\" />\n", flist.name().c_str(), xml_normalize_string(flist.value().c_str()));
+				fprintf(out, "\t\t\t\t<feature name=\"%s\" value=\"%s\" />\n", flist.name().c_str(), util::xml::normalize_string(flist.value().c_str()));
 
 			/* TODO: display rom region information */
 			for (const rom_entry *region = part.romdata().data(); region; region = rom_next_region(region))
@@ -1145,9 +1145,9 @@ void cli_frontend::output_single_softlist(FILE *out, software_list_device &swlis
 					if ( ROMENTRY_ISFILE(rom) )
 					{
 						if (!is_disk)
-							fprintf( out, "\t\t\t\t\t<rom name=\"%s\" size=\"%d\"", xml_normalize_string(ROM_GETNAME(rom)), rom_file_size(rom) );
+							fprintf( out, "\t\t\t\t\t<rom name=\"%s\" size=\"%d\"", util::xml::normalize_string(ROM_GETNAME(rom)), rom_file_size(rom) );
 						else
-							fprintf( out, "\t\t\t\t\t<disk name=\"%s\"", xml_normalize_string(ROM_GETNAME(rom)) );
+							fprintf( out, "\t\t\t\t\t<disk name=\"%s\"", util::xml::normalize_string(ROM_GETNAME(rom)) );
 
 						/* dump checksum information only if there is a known dump */
 						util::hash_collection hashes(ROM_GETHASHDATA(rom));
diff --git a/src/frontend/mame/info.cpp b/src/frontend/mame/info.cpp
index fe5ffad..0889dd7 100644
--- a/src/frontend/mame/info.cpp
+++ b/src/frontend/mame/info.cpp
@@ -216,7 +216,7 @@ void info_xml_creator::output(FILE *out, bool nodevices)
 #endif
 		"\" mameconfig=\"%d\">\n",
 		XML_ROOT,
-		xml_normalize_string(emulator_info::get_build_version()),
+		util::xml::normalize_string(emulator_info::get_build_version()),
 		CONFIG_VERSION
 	);
 
@@ -283,7 +283,7 @@ void info_xml_creator::output_one()
 
 	// print the header and the game name
 	fprintf(m_output, "\t<%s",XML_TOP);
-	fprintf(m_output, " name=\"%s\"", xml_normalize_string(driver.name));
+	fprintf(m_output, " name=\"%s\"", util::xml::normalize_string(driver.name));
 
 	// strip away any path information from the source_file and output it
 	const char *start = strrchr(driver.source_file, '/');
@@ -291,7 +291,7 @@ void info_xml_creator::output_one()
 		start = strrchr(driver.source_file, '\\');
 	if (start == nullptr)
 		start = driver.source_file - 1;
-	fprintf(m_output, " sourcefile=\"%s\"", xml_normalize_string(start + 1));
+	fprintf(m_output, " sourcefile=\"%s\"", util::xml::normalize_string(start + 1));
 
 	// append bios and runnable flags
 	if (driver.flags & MACHINE_IS_BIOS_ROOT)
@@ -304,9 +304,9 @@ void info_xml_creator::output_one()
 	// display clone information
 	int clone_of = m_drivlist.find(driver.parent);
 	if (clone_of != -1 && !(m_drivlist.driver(clone_of).flags & MACHINE_IS_BIOS_ROOT))
-		fprintf(m_output, " cloneof=\"%s\"", xml_normalize_string(m_drivlist.driver(clone_of).name));
+		fprintf(m_output, " cloneof=\"%s\"", util::xml::normalize_string(m_drivlist.driver(clone_of).name));
 	if (clone_of != -1)
-		fprintf(m_output, " romof=\"%s\"", xml_normalize_string(m_drivlist.driver(clone_of).name));
+		fprintf(m_output, " romof=\"%s\"", util::xml::normalize_string(m_drivlist.driver(clone_of).name));
 
 	// display sample information and close the game tag
 	output_sampleof();
@@ -314,15 +314,15 @@ void info_xml_creator::output_one()
 
 	// output game description
 	if (driver.description != nullptr)
-		fprintf(m_output, "\t\t<description>%s</description>\n", xml_normalize_string(driver.description));
+		fprintf(m_output, "\t\t<description>%s</description>\n", util::xml::normalize_string(driver.description));
 
 	// print the year only if is a number or another allowed character (? or +)
 	if (driver.year != nullptr && strspn(driver.year, "0123456789?+") == strlen(driver.year))
-		fprintf(m_output, "\t\t<year>%s</year>\n", xml_normalize_string(driver.year));
+		fprintf(m_output, "\t\t<year>%s</year>\n", util::xml::normalize_string(driver.year));
 
 	// print the manufacturer information
 	if (driver.manufacturer != nullptr)
-		fprintf(m_output, "\t\t<manufacturer>%s</manufacturer>\n", xml_normalize_string(driver.manufacturer));
+		fprintf(m_output, "\t\t<manufacturer>%s</manufacturer>\n", util::xml::normalize_string(driver.manufacturer));
 
 	// now print various additional information
 	output_bios();
@@ -376,15 +376,15 @@ void info_xml_creator::output_one_device(device_t &device, const char *devtag)
 
 	// start to output info
 	fprintf(m_output, "\t<%s", XML_TOP);
-	fprintf(m_output, " name=\"%s\"", xml_normalize_string(device.shortname()));
+	fprintf(m_output, " name=\"%s\"", util::xml::normalize_string(device.shortname()));
 	std::string src(device.source());
 	strreplace(src,"../", "");
-	fprintf(m_output, " sourcefile=\"%s\"", xml_normalize_string(src.c_str()));
+	fprintf(m_output, " sourcefile=\"%s\"", util::xml::normalize_string(src.c_str()));
 	fprintf(m_output, " isdevice=\"yes\"");
 	fprintf(m_output, " runnable=\"no\"");
 	output_sampleof();
 	fprintf(m_output, ">\n");
-	fprintf(m_output, "\t\t<description>%s</description>\n", xml_normalize_string(device.name()));
+	fprintf(m_output, "\t\t<description>%s</description>\n", util::xml::normalize_string(device.name()));
 
 	output_rom(device);
 
@@ -478,7 +478,7 @@ void info_xml_creator::output_device_roms()
 {
 	for (device_t &device : device_iterator(m_drivlist.config().root_device()))
 		if (device.owner() != nullptr && device.shortname() != nullptr && device.shortname()[0] != '\0')
-			fprintf(m_output, "\t\t<device_ref name=\"%s\"/>\n", xml_normalize_string(device.shortname()));
+			fprintf(m_output, "\t\t<device_ref name=\"%s\"/>\n", util::xml::normalize_string(device.shortname()));
 }
 
 
@@ -495,7 +495,7 @@ void info_xml_creator::output_sampleof()
 		samples_iterator sampiter(device);
 		if (sampiter.altbasename() != nullptr)
 		{
-			fprintf(m_output, " sampleof=\"%s\"", xml_normalize_string(sampiter.altbasename()));
+			fprintf(m_output, " sampleof=\"%s\"", util::xml::normalize_string(sampiter.altbasename()));
 
 			// must stop here, as there can only be one attribute of the same name
 			return;
@@ -529,8 +529,8 @@ void info_xml_creator::output_bios()
 		{
 			// output extracted name and descriptions
 			fprintf(m_output, "\t\t<biosset");
-			fprintf(m_output, " name=\"%s\"", xml_normalize_string(ROM_GETNAME(&rom)));
-			fprintf(m_output, " description=\"%s\"", xml_normalize_string(ROM_GETHASHDATA(&rom)));
+			fprintf(m_output, " name=\"%s\"", util::xml::normalize_string(ROM_GETNAME(&rom)));
+			fprintf(m_output, " description=\"%s\"", util::xml::normalize_string(ROM_GETHASHDATA(&rom)));
 			if (defaultname == ROM_GETNAME(&rom))
 				fprintf(m_output, " default=\"yes\"");
 			fprintf(m_output, "/>\n");
@@ -597,11 +597,11 @@ void info_xml_creator::output_rom(device_t &device)
 
 				// add name, merge, bios, and size tags */
 				if (name != nullptr && name[0] != 0)
-					util::stream_format(output, " name=\"%s\"", xml_normalize_string(name));
+					util::stream_format(output, " name=\"%s\"", util::xml::normalize_string(name));
 				if (merge_name != nullptr)
-					util::stream_format(output, " merge=\"%s\"", xml_normalize_string(merge_name));
+					util::stream_format(output, " merge=\"%s\"", util::xml::normalize_string(merge_name));
 				if (bios_name[0] != 0)
-					util::stream_format(output, " bios=\"%s\"", xml_normalize_string(bios_name));
+					util::stream_format(output, " bios=\"%s\"", util::xml::normalize_string(bios_name));
 				if (!is_disk)
 					util::stream_format(output, " size=\"%d\"", rom_file_size(rom));
 
@@ -659,7 +659,7 @@ void info_xml_creator::output_sample(device_t &device)
 				continue;
 
 			// output the sample name
-			fprintf(m_output, "\t\t<sample name=\"%s\"/>\n", xml_normalize_string(samplename));
+			fprintf(m_output, "\t\t<sample name=\"%s\"/>\n", util::xml::normalize_string(samplename));
 		}
 	}
 }
@@ -682,8 +682,8 @@ void info_xml_creator::output_chips(device_t &device, const char *root_tag)
 
 			fprintf(m_output, "\t\t<chip");
 			fprintf(m_output, " type=\"cpu\"");
-			fprintf(m_output, " tag=\"%s\"", xml_normalize_string(newtag.c_str()));
-			fprintf(m_output, " name=\"%s\"", xml_normalize_string(exec.device().name()));
+			fprintf(m_output, " tag=\"%s\"", util::xml::normalize_string(newtag.c_str()));
+			fprintf(m_output, " name=\"%s\"", util::xml::normalize_string(exec.device().name()));
 			fprintf(m_output, " clock=\"%d\"", exec.device().clock());
 			fprintf(m_output, "/>\n");
 		}
@@ -699,8 +699,8 @@ void info_xml_creator::output_chips(device_t &device, const char *root_tag)
 
 			fprintf(m_output, "\t\t<chip");
 			fprintf(m_output, " type=\"audio\"");
-			fprintf(m_output, " tag=\"%s\"", xml_normalize_string(newtag.c_str()));
-			fprintf(m_output, " name=\"%s\"", xml_normalize_string(sound.device().name()));
+			fprintf(m_output, " tag=\"%s\"", util::xml::normalize_string(newtag.c_str()));
+			fprintf(m_output, " name=\"%s\"", util::xml::normalize_string(sound.device().name()));
 			if (sound.device().clock() != 0)
 				fprintf(m_output, " clock=\"%d\"", sound.device().clock());
 			fprintf(m_output, "/>\n");
@@ -725,7 +725,7 @@ void info_xml_creator::output_display(device_t &device, const char *root_tag)
 			newtag = newtag.substr(newtag.find(oldtag.append(root_tag)) + oldtag.length());
 
 			fprintf(m_output, "\t\t<display");
-			fprintf(m_output, " tag=\"%s\"", xml_normalize_string(newtag.c_str()));
+			fprintf(m_output, " tag=\"%s\"", util::xml::normalize_string(newtag.c_str()));
 
 			switch (screendev.screen_type())
 			{
@@ -1230,7 +1230,7 @@ void info_xml_creator::output_input(const ioport_list &portlist)
 			//printf("type %s - player %d - buttons %d\n", elem.type, elem.player, elem.nbuttons);
 			if (elem.analog)
 			{
-				fprintf(m_output, "\t\t\t<control type=\"%s\"", xml_normalize_string(elem.type));
+				fprintf(m_output, "\t\t\t<control type=\"%s\"", util::xml::normalize_string(elem.type));
 				if (nplayer > 1)
 					fprintf(m_output, " player=\"%d\"", elem.player);
 				if (elem.nbuttons > 0)
@@ -1259,7 +1259,7 @@ void info_xml_creator::output_input(const ioport_list &portlist)
 				if (elem.helper[0] == 0 && elem.helper[1] != 0) { elem.helper[0] = elem.helper[1]; elem.helper[1] = 0; }
 				if (elem.helper[1] == 0 && elem.helper[2] != 0) { elem.helper[1] = elem.helper[2]; elem.helper[2] = 0; }
 				const char *joys = (elem.helper[2] != 0) ? "triple" : (elem.helper[1] != 0) ? "double" : "";
-				fprintf(m_output, "\t\t\t<control type=\"%s%s\"", joys, xml_normalize_string(elem.type));
+				fprintf(m_output, "\t\t\t<control type=\"%s%s\"", joys, util::xml::normalize_string(elem.type));
 				if (nplayer > 1)
 					fprintf(m_output, " player=\"%d\"", elem.player);
 				if (elem.nbuttons > 0)
@@ -1329,14 +1329,14 @@ void info_xml_creator::output_switches(const ioport_list &portlist, const char *
 				newtag = newtag.substr(newtag.find(oldtag.append(root_tag)) + oldtag.length());
 
 				// output the switch name information
-				std::string normalized_field_name(xml_normalize_string(field.name()));
-				std::string normalized_newtag(xml_normalize_string(newtag.c_str()));
+				std::string normalized_field_name(util::xml::normalize_string(field.name()));
+				std::string normalized_newtag(util::xml::normalize_string(newtag.c_str()));
 				util::stream_format(output,"\t\t<%s name=\"%s\" tag=\"%s\" mask=\"%u\">\n", outertag, normalized_field_name.c_str(), normalized_newtag.c_str(), field.mask());
 
 				// loop over settings
 				for (ioport_setting &setting : field.settings())
 				{
-					util::stream_format(output,"\t\t\t<%s name=\"%s\" value=\"%u\"%s/>\n", innertag, xml_normalize_string(setting.name()), setting.value(), setting.value() == field.defvalue() ? " default=\"yes\"" : "");
+					util::stream_format(output,"\t\t\t<%s name=\"%s\" value=\"%u\"%s/>\n", innertag, util::xml::normalize_string(setting.name()), setting.value(), setting.value() == field.defvalue() ? " default=\"yes\"" : "");
 				}
 
 				// terminate the switch entry
@@ -1355,7 +1355,7 @@ void info_xml_creator::output_ports(const ioport_list &portlist)
 	// cycle through ports
 	for (auto &port : portlist)
 	{
-		fprintf(m_output,"\t\t<port tag=\"%s\">\n", xml_normalize_string(port.second->tag()));
+		fprintf(m_output,"\t\t<port tag=\"%s\">\n", util::xml::normalize_string(port.second->tag()));
 		for (ioport_field &field : port.second->fields())
 		{
 			if(field.is_analog())
@@ -1378,7 +1378,7 @@ void info_xml_creator::output_adjusters(const ioport_list &portlist)
 	for (auto &port : portlist)
 		for (ioport_field &field : port.second->fields())
 			if (field.type() == IPT_ADJUSTER)
-				fprintf(m_output, "\t\t<adjuster name=\"%s\" default=\"%d\"/>\n", xml_normalize_string(field.name()), field.defvalue());
+				fprintf(m_output, "\t\t<adjuster name=\"%s\" default=\"%d\"/>\n", util::xml::normalize_string(field.name()), field.defvalue());
 }
 
 
@@ -1460,11 +1460,11 @@ void info_xml_creator::output_images(device_t &device, const char *root_tag)
 			newtag = newtag.substr(newtag.find(oldtag.append(root_tag)) + oldtag.length());
 
 			// print m_output device type
-			fprintf(m_output, "\t\t<device type=\"%s\"", xml_normalize_string(imagedev.image_type_name()));
+			fprintf(m_output, "\t\t<device type=\"%s\"", util::xml::normalize_string(imagedev.image_type_name()));
 
 			// does this device have a tag?
 			if (imagedev.device().tag())
-				fprintf(m_output, " tag=\"%s\"", xml_normalize_string(newtag.c_str()));
+				fprintf(m_output, " tag=\"%s\"", util::xml::normalize_string(newtag.c_str()));
 
 			// is this device available as media switch?
 			if (!loadable)
@@ -1475,7 +1475,7 @@ void info_xml_creator::output_images(device_t &device, const char *root_tag)
 				fprintf(m_output, " mandatory=\"1\"");
 
 			if (imagedev.image_interface() && imagedev.image_interface()[0])
-				fprintf(m_output, " interface=\"%s\"", xml_normalize_string(imagedev.image_interface()));
+				fprintf(m_output, " interface=\"%s\"", util::xml::normalize_string(imagedev.image_interface()));
 
 			// close the XML tag
 			fprintf(m_output, ">\n");
@@ -1486,8 +1486,8 @@ void info_xml_creator::output_images(device_t &device, const char *root_tag)
 				const char *shortname = imagedev.brief_instance_name();
 
 				fprintf(m_output, "\t\t\t<instance");
-				fprintf(m_output, " name=\"%s\"", xml_normalize_string(name));
-				fprintf(m_output, " briefname=\"%s\"", xml_normalize_string(shortname));
+				fprintf(m_output, " name=\"%s\"", util::xml::normalize_string(name));
+				fprintf(m_output, " briefname=\"%s\"", util::xml::normalize_string(shortname));
 				fprintf(m_output, "/>\n");
 
 				std::string extensions(imagedev.file_extensions());
@@ -1496,7 +1496,7 @@ void info_xml_creator::output_images(device_t &device, const char *root_tag)
 				while (ext != nullptr)
 				{
 					fprintf(m_output, "\t\t\t<extension");
-					fprintf(m_output, " name=\"%s\"", xml_normalize_string(ext));
+					fprintf(m_output, " name=\"%s\"", util::xml::normalize_string(ext));
 					fprintf(m_output, "/>\n");
 					ext = strtok(nullptr, ",");
 				}
@@ -1523,11 +1523,11 @@ void info_xml_creator::output_slots(device_t &device, const char *root_tag)
 			newtag = newtag.substr(newtag.find(oldtag.append(root_tag)) + oldtag.length());
 
 			// print m_output device type
-			fprintf(m_output, "\t\t<slot name=\"%s\">\n", xml_normalize_string(newtag.c_str()));
+			fprintf(m_output, "\t\t<slot name=\"%s\">\n", util::xml::normalize_string(newtag.c_str()));
 
 			/*
 			 if (slot.slot_interface()[0])
-			 fprintf(m_output, " interface=\"%s\"", xml_normalize_string(slot.slot_interface()));
+			 fprintf(m_output, " interface=\"%s\"", util::xml::normalize_string(slot.slot_interface()));
 			 */
 
 			for (auto &option : slot.option_list())
@@ -1539,8 +1539,8 @@ void info_xml_creator::output_slots(device_t &device, const char *root_tag)
 						dev->config_complete();
 
 					fprintf(m_output, "\t\t\t<slotoption");
-					fprintf(m_output, " name=\"%s\"", xml_normalize_string(option.second->name()));
-					fprintf(m_output, " devname=\"%s\"", xml_normalize_string(dev->shortname()));
+					fprintf(m_output, " name=\"%s\"", util::xml::normalize_string(option.second->name()));
+					fprintf(m_output, " devname=\"%s\"", util::xml::normalize_string(dev->shortname()));
 					if (slot.default_option() != nullptr && strcmp(slot.default_option(), option.second->name())==0)
 						fprintf(m_output, " default=\"yes\"");
 					fprintf(m_output, "/>\n");
diff --git a/src/frontend/mame/luaengine.cpp b/src/frontend/mame/luaengine.cpp
index 1bdc358..34d9c76 100644
--- a/src/frontend/mame/luaengine.cpp
+++ b/src/frontend/mame/luaengine.cpp
@@ -1219,7 +1219,7 @@ void lua_engine::initialize()
  * port:active() - get port status
  * port:live() - get port ioport_port_live (TODO: not usable from lua as of now)
  * port:read() - get port value
- * port:write(val, mask) - set port to value & mask
+ * port:write(val, mask) - set port to value & mask (output fields only, for other fields use field:set_value(val))
  * port:field(mask) - get ioport_field for port and mask
  * port.field[] - get ioport_field table
  */
diff --git a/src/frontend/mame/mame.cpp b/src/frontend/mame/mame.cpp
index b091348..c8e73eb 100644
--- a/src/frontend/mame/mame.cpp
+++ b/src/frontend/mame/mame.cpp
@@ -151,6 +151,11 @@ void mame_machine_manager::start_luaengine()
 			}
 		}
 	}
+	if (options().console()) {
+		std::string error_string;
+		m_plugins->set_value("console", "1", OPTION_PRIORITY_CMDLINE, error_string);
+	}
+
 	m_lua->initialize();
 
 	{
@@ -334,12 +339,12 @@ bool emulator_info::frame_hook()
 	return mame_machine_manager::instance()->lua()->frame_hook();
 }
 
-void emulator_info::layout_file_cb(xml_data_node &layout)
+void emulator_info::layout_file_cb(util::xml::data_node &layout)
 {
-	xml_data_node const *const mamelayout = layout.get_child("mamelayout");
+	util::xml::data_node const *const mamelayout = layout.get_child("mamelayout");
 	if (mamelayout)
 	{
-		xml_data_node const *const script = mamelayout->get_child("script");
+		util::xml::data_node const *const script = mamelayout->get_child("script");
 		if(script)
 			mame_machine_manager::instance()->lua()->call_plugin_set("layout", script->get_value());
 	}
diff --git a/src/frontend/mame/media_ident.cpp b/src/frontend/mame/media_ident.cpp
index 1360a88..3c1fdf1 100644
--- a/src/frontend/mame/media_ident.cpp
+++ b/src/frontend/mame/media_ident.cpp
@@ -235,7 +235,9 @@ int media_identifier::find_by_hash(const util::hash_collection &hashes, int leng
 							// output information about the match
 							if (found)
 								osd_printf_info("                    ");
-							osd_printf_info("= %s%-20s  %-10s %s\n", baddump ? "(BAD) " : "", ROM_GETNAME(rom), m_drivlist.driver().name, m_drivlist.driver().description);
+							osd_printf_info("= %s%-20s  %-10s %s%s\n", baddump ? "(BAD) " : "",
+								ROM_GETNAME(rom), device.shortname(), device.name(),
+								device.owner() != nullptr ? " (device)" : "");
 							found++;
 						}
 					}
diff --git a/src/frontend/mame/ui/filesel.cpp b/src/frontend/mame/ui/filesel.cpp
index 114fa31..6bd8486 100644
--- a/src/frontend/mame/ui/filesel.cpp
+++ b/src/frontend/mame/ui/filesel.cpp
@@ -22,7 +22,8 @@
 #include "zippath.h"
 
 #include <cstring>
-
+#include <locale>
+#include <codecvt>
 
 namespace ui {
 /***************************************************************************
@@ -297,6 +298,7 @@ void menu_file_selector::populate(float &customtop, float &custombottom)
 	const file_selector_entry *selected_entry = nullptr;
 	int i;
 	const char *volume_name;
+	uint8_t first;
 
 	// open the directory
 	err = util::zippath_opendir(m_current_directory, &directory);
@@ -332,6 +334,9 @@ void menu_file_selector::populate(float &customtop, float &custombottom)
 		i++;
 	}
 
+	// mark first filename entry
+	first = m_entrylist.size() + 1;
+
 	// build the menu for each item
 	if (err == osd_file::error::NONE)
 	{
@@ -353,6 +358,16 @@ void menu_file_selector::populate(float &customtop, float &custombottom)
 		}
 	}
 
+	// sort the menu entries
+	std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
+	const std::collate<wchar_t>& coll = std::use_facet<std::collate<wchar_t>>(std::locale());
+	std::sort(m_entrylist.begin()+first, m_entrylist.end(), [&coll, &conv](file_selector_entry const &x, file_selector_entry const &y)
+		{
+			std::wstring xstr = conv.from_bytes(x.basename);
+			std::wstring ystr = conv.from_bytes(y.basename);
+			return coll.compare(xstr.data(), xstr.data()+xstr.size(), ystr.data(), ystr.data()+ystr.size()) < 0;
+		} );
+
 	// append all of the menu entries
 	for (auto &entry : m_entrylist)
 		append_entry_menu_item(&entry);
diff --git a/src/frontend/mame/ui/filesel.h b/src/frontend/mame/ui/filesel.h
index a987e9f..6e17595 100644
--- a/src/frontend/mame/ui/filesel.h
+++ b/src/frontend/mame/ui/filesel.h
@@ -50,6 +50,9 @@ private:
 
 	struct file_selector_entry
 	{
+		file_selector_entry() {}
+		file_selector_entry(file_selector_entry &&) = default;
+		file_selector_entry &operator=(file_selector_entry &&) = default;
 		file_selector_entry_type type;
 		std::string basename;
 		std::string fullpath;
diff --git a/src/frontend/mame/ui/selmenu.cpp b/src/frontend/mame/ui/selmenu.cpp
index 84c0300..9c9ba40 100644
--- a/src/frontend/mame/ui/selmenu.cpp
+++ b/src/frontend/mame/ui/selmenu.cpp
@@ -78,8 +78,8 @@ menu_select_launch::cache::cache(running_machine &machine)
 	, m_snapx_texture()
 	, m_snapx_driver(nullptr)
 	, m_snapx_software(nullptr)
-	, m_no_avail_bitmap(std::make_unique<bitmap_argb32>(256, 256))
-	, m_star_bitmap(std::make_unique<bitmap_argb32>(32, 32))
+	, m_no_avail_bitmap(256, 256)
+	, m_star_bitmap(32, 32)
 	, m_star_texture()
 	, m_toolbar_bitmap()
 	, m_sw_toolbar_bitmap()
@@ -92,11 +92,11 @@ menu_select_launch::cache::cache(running_machine &machine)
 	// create a texture for snapshot
 	m_snapx_texture = texture_ptr(render.texture_alloc(render_texture::hq_scale), texture_free);
 
-	std::memcpy(&m_no_avail_bitmap->pix32(0), no_avail_bmp, 256 * 256 * sizeof(uint32_t));
+	std::memcpy(&m_no_avail_bitmap.pix32(0), no_avail_bmp, 256 * 256 * sizeof(uint32_t));
 
-	std::memcpy(&m_star_bitmap->pix32(0), favorite_star_bmp, 32 * 32 * sizeof(uint32_t));
+	std::memcpy(&m_star_bitmap.pix32(0), favorite_star_bmp, 32 * 32 * sizeof(uint32_t));
 	m_star_texture = texture_ptr(render.texture_alloc(), texture_free);
-	m_star_texture->set_bitmap(*m_star_bitmap, m_star_bitmap->cliprect(), TEXFORMAT_ARGB32);
+	m_star_texture->set_bitmap(m_star_bitmap, m_star_bitmap.cliprect(), TEXFORMAT_ARGB32);
 
 	m_toolbar_bitmap.reserve(UI_TOOLBAR_BUTTONS);
 	m_sw_toolbar_bitmap.reserve(UI_TOOLBAR_BUTTONS);
@@ -105,28 +105,28 @@ menu_select_launch::cache::cache(running_machine &machine)
 
 	for (std::size_t i = 0; i < UI_TOOLBAR_BUTTONS; ++i)
 	{
-		m_toolbar_bitmap.emplace_back(std::make_unique<bitmap_argb32>(32, 32));
-		m_sw_toolbar_bitmap.emplace_back(std::make_unique<bitmap_argb32>(32, 32));
+		m_toolbar_bitmap.emplace_back(32, 32);
+		m_sw_toolbar_bitmap.emplace_back(32, 32);
 		m_toolbar_texture.emplace_back(texture_ptr(render.texture_alloc(), texture_free));
 		m_sw_toolbar_texture.emplace_back(texture_ptr(render.texture_alloc(), texture_free));
 
-		std::memcpy(&m_toolbar_bitmap.back()->pix32(0), toolbar_bitmap_bmp[i], 32 * 32 * sizeof(uint32_t));
-		if (m_toolbar_bitmap.back()->valid())
-			m_toolbar_texture.back()->set_bitmap(*m_toolbar_bitmap.back(), m_toolbar_bitmap.back()->cliprect(), TEXFORMAT_ARGB32);
+		std::memcpy(&m_toolbar_bitmap.back().pix32(0), toolbar_bitmap_bmp[i], 32 * 32 * sizeof(uint32_t));
+		if (m_toolbar_bitmap.back().valid())
+			m_toolbar_texture.back()->set_bitmap(m_toolbar_bitmap.back(), m_toolbar_bitmap.back().cliprect(), TEXFORMAT_ARGB32);
 		else
-			m_toolbar_bitmap.back()->reset();
+			m_toolbar_bitmap.back().reset();
 
 		if ((i == 0U) || (i == 2U))
 		{
-			std::memcpy(&m_sw_toolbar_bitmap.back()->pix32(0), toolbar_bitmap_bmp[i], 32 * 32 * sizeof(uint32_t));
-			if (m_sw_toolbar_bitmap.back()->valid())
-				m_sw_toolbar_texture.back()->set_bitmap(*m_sw_toolbar_bitmap.back(), m_sw_toolbar_bitmap.back()->cliprect(), TEXFORMAT_ARGB32);
+			std::memcpy(&m_sw_toolbar_bitmap.back().pix32(0), toolbar_bitmap_bmp[i], 32 * 32 * sizeof(uint32_t));
+			if (m_sw_toolbar_bitmap.back().valid())
+				m_sw_toolbar_texture.back()->set_bitmap(m_sw_toolbar_bitmap.back(), m_sw_toolbar_bitmap.back().cliprect(), TEXFORMAT_ARGB32);
 			else
-				m_sw_toolbar_bitmap.back()->reset();
+				m_sw_toolbar_bitmap.back().reset();
 		}
 		else
 		{
-			m_sw_toolbar_bitmap.back()->reset();
+			m_sw_toolbar_bitmap.back().reset();
 		}
 	}
 }
@@ -139,12 +139,6 @@ menu_select_launch::cache::~cache()
 
 menu_select_launch::~menu_select_launch()
 {
-	// need to manually clean up icon textures for now
-	for (auto &texture : m_icons_texture)
-	{
-		if (texture)
-			machine().render().texture_free(texture);
-	}
 }
 
 
@@ -164,6 +158,7 @@ menu_select_launch::menu_select_launch(mame_ui_manager &mui, render_container &c
 	, m_pressed(false)
 	, m_repeat(0)
 	, m_right_visible_lines(0)
+	, m_icons(MAX_ICONS_RENDER)
 {
 	// set up persistent cache for machine run
 	{
@@ -181,18 +176,6 @@ menu_select_launch::menu_select_launch(mame_ui_manager &mui, render_container &c
 			add_cleanup_callback(&menu_select_launch::exit);
 		}
 	}
-
-	// initialise icon cache
-	if (is_swlist)
-	{
-		std::fill(std::begin(m_icons_texture), std::end(m_icons_texture), nullptr);
-	}
-	else
-	{
-		std::generate(std::begin(m_icons_texture), std::end(m_icons_texture), [&render = machine().render()]() { return render.texture_alloc(); });
-		std::generate(std::begin(m_icons_bitmap), std::end(m_icons_bitmap), []() { return std::make_unique<bitmap_argb32>(); });
-	}
-	std::fill(std::begin(m_old_icons), std::end(m_old_icons), nullptr);
 }
 
 
@@ -551,9 +534,9 @@ void menu_select_launch::draw_toolbar(float x1, float y1, float x2, float y2)
 	y2 -= UI_BOX_TB_BORDER;
 
 	texture_ptr_vector const &t_texture(m_is_swlist ? m_cache->sw_toolbar_texture() : m_cache->toolbar_texture());
-	bitmap_ptr_vector const &t_bitmap(m_is_swlist ? m_cache->sw_toolbar_bitmap() : m_cache->toolbar_bitmap());
+	bitmap_vector const &t_bitmap(m_is_swlist ? m_cache->sw_toolbar_bitmap() : m_cache->toolbar_bitmap());
 
-	auto const num_valid(std::count_if(std::begin(t_bitmap), std::end(t_bitmap), [](bitmap_ptr const &e) { return e && e->valid(); }));
+	auto const num_valid(std::count_if(std::begin(t_bitmap), std::end(t_bitmap), [](bitmap_argb32 const &e) { return e.valid(); }));
 
 	float const space_x = (y2 - y1) * container().manager().ui_aspect(&container());
 	float const total = (float(num_valid) * space_x) + (float(num_valid - 1) * 0.001f);
@@ -562,7 +545,7 @@ void menu_select_launch::draw_toolbar(float x1, float y1, float x2, float y2)
 
 	for (int z = 0; z < UI_TOOLBAR_BUTTONS; ++z)
 	{
-		if (t_bitmap[z] && t_bitmap[z]->valid())
+		if (t_bitmap[z].valid())
 		{
 			rgb_t color(0xEFEFEFEF);
 			if (mouse_in_rect(x1, y1, x2, y2))
@@ -624,9 +607,17 @@ float menu_select_launch::draw_icon(int linenum, void *selectedref, float x0, fl
 	auto x1 = x0 + ud_arrow_width;
 	auto y1 = y0 + ui().get_line_height();
 
-	if (m_old_icons[linenum] != driver || ui_globals::redraw_icon)
+	icon_cache::iterator icon(m_icons.find(driver));
+	if ((m_icons.end() == icon) || ui_globals::redraw_icon)
 	{
-		m_old_icons[linenum] = driver;
+		if (m_icons.end() == icon)
+		{
+			texture_ptr texture(machine().render().texture_alloc(), [&render = machine().render()] (render_texture *texture) { render.texture_free(texture); });
+			icon = m_icons.emplace(
+					std::piecewise_construct,
+					std::forward_as_tuple(driver),
+					std::forward_as_tuple(std::piecewise_construct, std::forward_as_tuple(std::move(texture)), std::tuple<>())).first;
+		}
 
 		// set clone status
 		bool cloneof = strcmp(driver->parent, "0");
@@ -657,6 +648,7 @@ float menu_select_launch::draw_icon(int linenum, void *selectedref, float x0, fl
 			render_load_ico(*tmp, snapfile, nullptr, fullname.c_str());
 		}
 
+		bitmap_argb32 &bitmap(icon->second.second);
 		if (tmp->valid())
 		{
 			float panel_width = x1 - x0;
@@ -697,24 +689,25 @@ float menu_select_launch::draw_icon(int linenum, void *selectedref, float x0, fl
 			else
 				dest_bitmap = tmp;
 
-			m_icons_bitmap[linenum]->allocate(panel_width_pixel, panel_height_pixel);
-
+			bitmap.allocate(panel_width_pixel, panel_height_pixel);
 			for (int x = 0; x < dest_xPixel; x++)
 				for (int y = 0; y < dest_yPixel; y++)
-					m_icons_bitmap[linenum]->pix32(y, x) = dest_bitmap->pix32(y, x);
+					bitmap.pix32(y, x) = dest_bitmap->pix32(y, x);
 
 			auto_free(machine(), dest_bitmap);
 
-			m_icons_texture[linenum]->set_bitmap(*m_icons_bitmap[linenum], m_icons_bitmap[linenum]->cliprect(), TEXFORMAT_ARGB32);
+			icon->second.first->set_bitmap(bitmap, bitmap.cliprect(), TEXFORMAT_ARGB32);
+		}
+		else
+		{
+			bitmap.reset();
 		}
-		else if (m_icons_bitmap[linenum] != nullptr)
-			m_icons_bitmap[linenum]->reset();
 
 		auto_free(machine(), tmp);
 	}
 
-	if (m_icons_bitmap[linenum] != nullptr && m_icons_bitmap[linenum]->valid())
-		container().add_quad(x0, y0, x1, y1, rgb_t::white(), m_icons_texture[linenum], PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+	if (icon->second.second.valid())
+		container().add_quad(x0, y0, x1, y1, rgb_t::white(), icon->second.first.get(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
 
 	return ud_arrow_width * 1.5f;
 }
diff --git a/src/frontend/mame/ui/selmenu.h b/src/frontend/mame/ui/selmenu.h
index f5d4dea..6bd63b4 100644
--- a/src/frontend/mame/ui/selmenu.h
+++ b/src/frontend/mame/ui/selmenu.h
@@ -62,7 +62,7 @@ protected:
 	bool    m_ui_error;
 
 private:
-	using bitmap_ptr_vector = std::vector<bitmap_ptr>;
+	using bitmap_vector = std::vector<bitmap_argb32>;
 	using texture_ptr_vector = std::vector<texture_ptr>;
 
 	class cache
@@ -78,11 +78,11 @@ private:
 		void set_snapx_driver(game_driver const *value) { m_snapx_driver = value; }
 		void set_snapx_software(ui_software_info const *software) { m_snapx_software = software; }
 
-		bitmap_argb32 &no_avail_bitmap() { return *m_no_avail_bitmap; }
+		bitmap_argb32 &no_avail_bitmap() { return m_no_avail_bitmap; }
 		render_texture *star_texture() { return m_star_texture.get(); }
 
-		bitmap_ptr_vector const &toolbar_bitmap() { return m_toolbar_bitmap; }
-		bitmap_ptr_vector const &sw_toolbar_bitmap() { return m_sw_toolbar_bitmap; }
+		bitmap_vector const &toolbar_bitmap() { return m_toolbar_bitmap; }
+		bitmap_vector const &sw_toolbar_bitmap() { return m_sw_toolbar_bitmap; }
 		texture_ptr_vector const &toolbar_texture() { return m_toolbar_texture; }
 		texture_ptr_vector const &sw_toolbar_texture() { return m_sw_toolbar_texture; }
 
@@ -92,19 +92,21 @@ private:
 		game_driver const       *m_snapx_driver;
 		ui_software_info const  *m_snapx_software;
 
-		bitmap_ptr              m_no_avail_bitmap;
-		bitmap_ptr              m_star_bitmap;
+		bitmap_argb32           m_no_avail_bitmap;
+		bitmap_argb32           m_star_bitmap;
 		texture_ptr             m_star_texture;
 
-		bitmap_ptr_vector       m_toolbar_bitmap;
-		bitmap_ptr_vector       m_sw_toolbar_bitmap;
+		bitmap_vector           m_toolbar_bitmap;
+		bitmap_vector           m_sw_toolbar_bitmap;
 		texture_ptr_vector      m_toolbar_texture;
 		texture_ptr_vector      m_sw_toolbar_texture;
 	};
 	using cache_ptr = std::shared_ptr<cache>;
 	using cache_ptr_map = std::map<running_machine *, cache_ptr>;
 
-	static constexpr std::size_t MAX_ICONS_RENDER = 40;
+	using icon_cache = util::lru_cache_map<game_driver const *, std::pair<texture_ptr, bitmap_argb32> >;
+
+	static constexpr std::size_t MAX_ICONS_RENDER = 128;
 
 	void reset_pressed() { m_pressed = false; m_repeat = 0; }
 	bool mouse_pressed() const { return (osd_ticks() >= m_repeat); }
@@ -115,11 +117,11 @@ private:
 	// draw left panel
 	virtual float draw_left_panel(float x1, float y1, float x2, float y2) = 0;
 
-	game_driver const       *m_info_driver;
-	ui_software_info const  *m_info_software;
-	int                      m_info_view;
-	std::vector<std::string> m_items_list;
-	std::string              m_info_buffer;
+	game_driver const           *m_info_driver;
+	ui_software_info const      *m_info_software;
+	int                         m_info_view;
+	std::vector<std::string>    m_items_list;
+	std::string                 m_info_buffer;
 
 	// draw infos
 	void infos_render(float x1, float y1, float x2, float y2);
@@ -187,10 +189,7 @@ private:
 
 	int                     m_right_visible_lines;  // right box lines
 
-
-	render_texture          *m_icons_texture[MAX_ICONS_RENDER];
-	bitmap_ptr              m_icons_bitmap[MAX_ICONS_RENDER];
-	game_driver const       *m_old_icons[MAX_ICONS_RENDER];
+	icon_cache              m_icons;
 
 	static std::mutex       s_cache_guard;
 	static cache_ptr_map    s_caches;
diff --git a/src/lib/formats/acorn_dsk.cpp b/src/lib/formats/acorn_dsk.cpp
index b880b28..0c62a90 100644
--- a/src/lib/formats/acorn_dsk.cpp
+++ b/src/lib/formats/acorn_dsk.cpp
@@ -412,8 +412,8 @@ int acorn_adfs_new_format::find_size(io_generic *io, uint32_t form_factor)
 		if (form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor)
 			continue;
 
-		// valid images will have map identifier Nick
-		if ((size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count) && (memcmp(dform, "Nick", 4) == 0 || memcmp(eform, "Nick", 4) == 0)) {
+		// valid images will have map identifier Nick, Arthur D format still use Hugo
+		if ((size <= (uint64_t)compute_track_size(f) * f.track_count * f.head_count) && (memcmp(dform, "Nick", 4) == 0 || memcmp(eform, "Nick", 4) == 0 || memcmp(dform, "Hugo", 4) == 0)) {
 			return i;
 		}
 	}
diff --git a/src/lib/netlist/analog/nld_opamps.cpp b/src/lib/netlist/analog/nld_opamps.cpp
index 57d6f6a..d587f69 100644
--- a/src/lib/netlist/analog/nld_opamps.cpp
+++ b/src/lib/netlist/analog/nld_opamps.cpp
@@ -48,6 +48,22 @@ namespace netlist
  *        2; opamp with first pole
  *        3: opamp with first pole + output limit
  *        4: opamp with input stage, first pole + output limit
+ *
+ * Type 1 parameters:
+ *     FPF = frequency of first pole in Hz (ony used for open-loop gain)
+ *     UGF = unity gain frequency in Hz (only used for open-loop gain)
+ *     RI = input resistance in Ohms
+ *     RO = output resistance in Ohms
+ *
+ * Type 3 parameters:
+ *     VLH = high supply rail minus high output swing in V
+ *     VLL = low output swing minus low supply rail in V
+ *     FPF = frequency of first pole in Hz
+ *     UGF = unity gain frequency (transition frequency) in Hz
+ *     SLEW = unity gain slew rate in V/s
+ *     RI = input resistance in Ohms
+ *     RO = output resistance in Ohms
+ *     DAB = quiescent supply current in A
  */
 
 /* .model abc OPAMP(VLH=2.0 VLL=0.2 FPF=5 UGF=10k SLEW=0.6u RI=1000k RO=50 DAB=0.002)
diff --git a/src/lib/netlist/analog/nld_twoterm.cpp b/src/lib/netlist/analog/nld_twoterm.cpp
index 3ddff27..089b11f 100644
--- a/src/lib/netlist/analog/nld_twoterm.cpp
+++ b/src/lib/netlist/analog/nld_twoterm.cpp
@@ -117,6 +117,27 @@ NETLIB_UPDATE(C)
 }
 
 // ----------------------------------------------------------------------------------------
+// nld_L
+// ----------------------------------------------------------------------------------------
+
+NETLIB_RESET(L)
+{
+	set(netlist().gmin(), 0.0, 5.0 / netlist().gmin());
+	//set(1.0/NETLIST_GMIN, 0.0, -5.0 * NETLIST_GMIN);
+}
+
+NETLIB_UPDATE_PARAM(L)
+{
+	//step_time(1.0/48000.0);
+	//m_GParallel = netlist().gmin() / m_L();
+}
+
+NETLIB_UPDATE(L)
+{
+	NETLIB_NAME(twoterm)::update();
+}
+
+// ----------------------------------------------------------------------------------------
 // nld_D
 // ----------------------------------------------------------------------------------------
 
diff --git a/src/lib/netlist/analog/nld_twoterm.h b/src/lib/netlist/analog/nld_twoterm.h
index b5de48a..f59b9e6 100644
--- a/src/lib/netlist/analog/nld_twoterm.h
+++ b/src/lib/netlist/analog/nld_twoterm.h
@@ -40,34 +40,38 @@
 // -----------------------------------------------------------------------------
 
 #define RES(name, p_R)                                                         \
-		NET_REGISTER_DEV(RES, name)                                           \
+		NET_REGISTER_DEV(RES, name)                                            \
 		NETDEV_PARAMI(name, R, p_R)
 
 #define POT(name, p_R)                                                         \
-		NET_REGISTER_DEV(POT, name)                                           \
+		NET_REGISTER_DEV(POT, name)                                            \
 		NETDEV_PARAMI(name, R, p_R)
 
 /* Does not have pin 3 connected */
 #define POT2(name, p_R)                                                        \
-		NET_REGISTER_DEV(POT2, name)                                          \
+		NET_REGISTER_DEV(POT2, name)                                           \
 		NETDEV_PARAMI(name, R, p_R)
 
 
 #define CAP(name, p_C)                                                         \
-		NET_REGISTER_DEV(CAP, name)                                           \
+		NET_REGISTER_DEV(CAP, name)                                            \
 		NETDEV_PARAMI(name, C, p_C)
 
+#define IND(name, p_L)                                                         \
+		NET_REGISTER_DEV(IND, name)                                            \
+		NETDEV_PARAMI(name, L, p_L)
+
 /* Generic Diode */
-#define DIODE(name,  model)                                                  \
-		NET_REGISTER_DEV(DIODE, name)                                         \
+#define DIODE(name,  model)                                                    \
+		NET_REGISTER_DEV(DIODE, name)                                          \
 		NETDEV_PARAMI(name, MODEL, model)
 
-#define VS(name, pV)                                                          \
-		NET_REGISTER_DEV(VS, name)                                            \
+#define VS(name, pV)                                                           \
+		NET_REGISTER_DEV(VS, name)                                             \
 		NETDEV_PARAMI(name, V, pV)
 
-#define CS(name, pI)                                                          \
-		NET_REGISTER_DEV(CS, name)                                            \
+#define CS(name, pI)                                                           \
+		NET_REGISTER_DEV(CS, name)                                             \
 		NETDEV_PARAMI(name, I, pI)
 
 // -----------------------------------------------------------------------------
@@ -303,6 +307,43 @@ private:
 
 };
 
+// -----------------------------------------------------------------------------
+// nld_L
+// -----------------------------------------------------------------------------
+
+NETLIB_OBJECT_DERIVED(L, twoterm)
+{
+public:
+	NETLIB_CONSTRUCTOR_DERIVED(L, twoterm)
+	, m_L(*this, "L", 1e-6)
+	, m_GParallel(0.0)
+	, m_G(0.0)
+	, m_I(0.0)
+	{
+		//register_term("1", m_P);
+		//register_term("2", m_N);
+	}
+
+	NETLIB_TIMESTEP()
+	{
+		/* Gpar should support convergence */
+		m_I = m_I + m_G * deltaV();
+		m_G = step / m_L() + m_GParallel;
+		set(m_G, 0.0, m_I);
+	}
+
+	param_double_t m_L;
+
+protected:
+	NETLIB_RESETI();
+	NETLIB_UPDATEI();
+	NETLIB_UPDATE_PARAMI();
+
+private:
+	nl_double m_GParallel;
+	nl_double m_G;
+	nl_double m_I;
+};
 
 // -----------------------------------------------------------------------------
 // A generic diode model to be used in other devices (Diode, BJT ...)
diff --git a/src/lib/netlist/build/makefile b/src/lib/netlist/build/makefile
index 36bce29..f971065 100644
--- a/src/lib/netlist/build/makefile
+++ b/src/lib/netlist/build/makefile
@@ -66,29 +66,48 @@ NLOBJS := \
 	$(NLOBJ)/analog/nld_switches.o \
 	$(NLOBJ)/analog/nld_twoterm.o \
 	$(NLOBJ)/analog/nld_opamps.o \
+	$(NLOBJ)/devices/nld_2102A.o \
+	$(NLOBJ)/devices/nld_2716.o \
 	$(NLOBJ)/devices/nld_4020.o \
 	$(NLOBJ)/devices/nld_4066.o \
+	$(NLOBJ)/devices/nld_4316.o \
 	$(NLOBJ)/devices/nld_7448.o \
 	$(NLOBJ)/devices/nld_7450.o \
+	$(NLOBJ)/devices/nld_7473.o \
 	$(NLOBJ)/devices/nld_7474.o \
+	$(NLOBJ)/devices/nld_7475.o \
 	$(NLOBJ)/devices/nld_7483.o \
+	$(NLOBJ)/devices/nld_7485.o \
 	$(NLOBJ)/devices/nld_7490.o \
 	$(NLOBJ)/devices/nld_7493.o \
 	$(NLOBJ)/devices/nld_74107.o \
 	$(NLOBJ)/devices/nld_74123.o \
 	$(NLOBJ)/devices/nld_74153.o \
+	$(NLOBJ)/devices/nld_74161.o \
+	$(NLOBJ)/devices/nld_74165.o \
+	$(NLOBJ)/devices/nld_74166.o \
+	$(NLOBJ)/devices/nld_74174.o \
 	$(NLOBJ)/devices/nld_74175.o \
 	$(NLOBJ)/devices/nld_74192.o \
 	$(NLOBJ)/devices/nld_74193.o \
+	$(NLOBJ)/devices/nld_74194.o \
 	$(NLOBJ)/devices/nld_74279.o \
+	$(NLOBJ)/devices/nld_74365.o \
 	$(NLOBJ)/devices/nld_74ls629.o \
 	$(NLOBJ)/devices/nld_82S16.o \
+	$(NLOBJ)/devices/nld_82S115.o \
+	$(NLOBJ)/devices/nld_82S123.o \
+	$(NLOBJ)/devices/nld_82S126.o \
 	$(NLOBJ)/devices/nld_9310.o \
 	$(NLOBJ)/devices/nld_9312.o \
 	$(NLOBJ)/devices/nld_9316.o \
+	$(NLOBJ)/devices/nld_9322.o \
+	$(NLOBJ)/devices/nld_am2847.o \
+	$(NLOBJ)/devices/nld_dm9334.o \
 	$(NLOBJ)/devices/nld_mm5837.o \
 	$(NLOBJ)/devices/nld_ne555.o \
 	$(NLOBJ)/devices/nld_r2r_dac.o \
+	$(NLOBJ)/devices/nld_tristate.o \
 	$(NLOBJ)/devices/nld_legacy.o \
 	$(NLOBJ)/devices/net_lib.o \
 	$(NLOBJ)/devices/nld_log.o \
@@ -124,7 +143,7 @@ clean:
 
 nltool: $(OBJ)/prg/nltool.o $(OBJS)
 	@echo Linking $@...
-	$(LD) -o $@ $(LDFLAGS) $^ $(LIBS) 
+	$(LD) -o $@ $(LDFLAGS) $^ $(LIBS)
 
 nlwav: $(OBJ)/prg/nlwav.o $(OBJS)
 	@echo Linking $@...
@@ -145,14 +164,14 @@ maketree: $(sort $(OBJDIRS))
 
 .PHONY: clang mingw doc
 
-clang: 
+clang:
 	$(MAKE) CC=clang++ LD=clang++ CEXTRAFLAGS="-Weverything -Werror -Wno-padded -Wno-weak-vtables -Wno-missing-variable-declarations -Wconversion -Wno-c++98-compat -Wno-float-equal -Wno-cast-align -Wno-global-constructors -Wno-c++98-compat-pedantic -Wno-exit-time-destructors -Wno-format-nonliteral -Wno-weak-template-vtables"
 
-# 
-# FIXME:  -Wno-weak-vtables -Wno-missing-variable-declarations -Wno-conversion -Wno-exit-time-destructors 
-# 
+#
+# FIXME:  -Wno-weak-vtables -Wno-missing-variable-declarations -Wno-conversion -Wno-exit-time-destructors
+#
 
-mingw: 
+mingw:
 	$(MAKE) LDEXTRAFLAGS="-Wl,--subsystem,console" LIBS= MD=@mkdir.exe SHELL=sh.exe
 
 #
@@ -191,7 +210,7 @@ $(OBJ)/%.o: $(SRC)/%.cpp
 	@echo Compiling $<...
 	@$(CC) $(CDEFS) $(CFLAGS) -c $< -o $@
 
-$(OBJ)/%.pp: $(SRC)/%.cpp 
+$(OBJ)/%.pp: $(SRC)/%.cpp
 	@echo Compiling $<...
 	@$(CC) $(CDEFS) $(CFLAGS) -E $< -o $@
 
diff --git a/src/lib/netlist/devices/net_lib.cpp b/src/lib/netlist/devices/net_lib.cpp
index f70e229..b989fdd 100644
--- a/src/lib/netlist/devices/net_lib.cpp
+++ b/src/lib/netlist/devices/net_lib.cpp
@@ -77,6 +77,7 @@ static void initialize_factory(factory_list_t &factory)
 	ENTRY(POT,                  POT,                    "R")
 	ENTRY(POT2,                 POT2,                   "R")
 	ENTRY(C,                    CAP,                    "C")
+	ENTRY(L,                    IND,                    "L")
 	ENTRY(D,                    DIODE,                  "MODEL")
 	ENTRY(VCVS,                 VCVS,                   "-")
 	ENTRY(VCCS,                 VCCS,                   "-")
@@ -105,26 +106,45 @@ static void initialize_factory(factory_list_t &factory)
 	ENTRY(switch1,              SWITCH,                 "-")
 	ENTRY(switch2,              SWITCH2,                "-")
 	ENTRYX(nicRSFF,             NETDEV_RSFF,            "+S,R")
-	ENTRYX(nicDelay,            NETDEV_DELAY,            "-")
+	ENTRYX(nicDelay,            NETDEV_DELAY,           "-")
+	ENTRYX(2716,                EPROM_2716,             "+GQ,EPQ,A0,A1,A2,A3,A4,A5,A6,A7,A8,A9,A10")
+	ENTRYX(2102A,               RAM_2102A,              "+CEQ,A0,A1,A2,A3,A4,A5,A6,A7,A8,A9,RWQ,DI")
 	ENTRYX(7450,                TTL_7450_ANDORINVERT,   "+A,B,C,D")
 	ENTRYX(7448,                TTL_7448,               "+A,B,C,D,LTQ,BIQ,RBIQ")
+	ENTRYX(7473,                TTL_7473,               "+CLK,J,K,CLRQ")
+	ENTRYX(7473A,               TTL_7473A,              "+CLK,J,K,CLRQ")
 	ENTRYX(7474,                TTL_7474,               "+CLK,D,CLRQ,PREQ")
+	ENTRYX(7475,                TTL_7475,               "-")
+	ENTRYX(7477,                TTL_7477,               "-")
 	ENTRYX(7483,                TTL_7483,               "+A1,A2,A3,A4,B1,B2,B3,B4,C0")
+	ENTRYX(7485,                TTL_7485,               "-")
 	ENTRYX(7490,                TTL_7490,               "+A,B,R1,R2,R91,R92")
 	ENTRYX(7493,                TTL_7493,               "+CLKA,CLKB,R1,R2")
 	ENTRYX(74107,               TTL_74107,              "+CLK,J,K,CLRQ")
 	ENTRYX(74107A,              TTL_74107A,             "+CLK,J,K,CLRQ")
 	ENTRYX(74123,               TTL_74123,              "-")
 	ENTRYX(74153,               TTL_74153,              "+C0,C1,C2,C3,A,B,G")
-	ENTRYX(74175,               TTL_74175,              "-")
+	ENTRYX(74161,               TTL_74161,              "+A,B,C,D,CLRQ,LOADQ,CLK,ENABLEP,ENABLET")
+	ENTRYX(74165,               TTL_74165,              "-")
+	ENTRYX(74166,               TTL_74166,              "+CLK,CLKINH,SH_LDQ,SER,A,B,C,D,E,F,G,H,CLRQ")
+	ENTRYX(74174,               TTL_74174,              "+CLK,D1,D2,D3,D4,D5,D6,CLRQ")
+	ENTRYX(74175,               TTL_74175,              "+CLK,D1,D2,D3,D4,CLRQ")
 	ENTRYX(74192,               TTL_74192,              "-")
-	ENTRYX(74193,               TTL_74193,              "-")
+	ENTRYX(74193,               TTL_74193,              "+A,B,C,D,CLEAR,LOADQ,CU,CD")
+	ENTRYX(74194,               TTL_74194,              "-")
+	ENTRYX(74365,               TTL_74365,              "+G1Q,G2Q,A1,A2,A3,A4,A5,A6")
 	//ENTRY(74279,              TTL_74279,              "-") // only dip available
 	ENTRYX(SN74LS629,           SN74LS629,              "CAP")
 	ENTRYX(82S16,               TTL_82S16,              "-")
+	ENTRYX(82S115,              PROM_82S115,            "-")
+	ENTRYX(82S123,              PROM_82S123,            "-")
+	ENTRYX(82S126,              PROM_82S126,            "+CE1Q,CE2Q,A0,A1,A2,A3,A4,A5,A6,A7")
 	ENTRYX(9310,                TTL_9310,               "-")
 	ENTRYX(9312,                TTL_9312,               "-")
 	ENTRYX(9316,                TTL_9316,               "+CLK,ENP,ENT,CLRQ,LOADQ,A,B,C,D")
+	ENTRYX(9322,                TTL_9322,               "-")
+	ENTRYX(9334,                TTL_9334,               "+CQ,EQ,D,A0,A1,A2")
+	ENTRYX(AM2847,              TTL_AM2847,             "+CP,INA,INB,INC,IND,RCA,RCB,RCC,RCD")
 	ENTRYX(CD4020,              CD4020,                 "")
 	ENTRYX(CD4066_GATE,         CD4066_GATE,            "")
 	/* entries with suffix WI are legacy only */
@@ -132,25 +152,46 @@ static void initialize_factory(factory_list_t &factory)
 	//ENTRY(4066,                 CD_4066,              "+A,B")
 	ENTRYX(NE555,               NE555,                  "-")
 	ENTRYX(r2r_dac,             R2R_DAC,                "+VIN,R,N")
+	ENTRYX(tristate,            TTL_TRISTATE,           "+CEQ1,D1,CEQ2,D2")
+	ENTRYX(tristate3,           TTL_TRISTATE3,          "-")
+	ENTRYX(2102A_dip,           RAM_2102A_DIP,          "-")
+	ENTRYX(2716_dip,            EPROM_2716_DIP,         "-")
 	ENTRYX(4538_dip,            CD4538_DIP,             "-")
 	ENTRYX(7448_dip,            TTL_7448_DIP,           "-")
 	ENTRYX(7450_dip,            TTL_7450_DIP,           "-")
+	ENTRYX(7473_dip,            TTL_7473_DIP,           "-")
+	ENTRYX(7473A_dip,           TTL_7473A_DIP,          "-")
 	ENTRYX(7474_dip,            TTL_7474_DIP,           "-")
+	ENTRYX(7475_dip,            TTL_7475_DIP,           "-")
+	ENTRYX(7477_dip,            TTL_7477_DIP,           "-")
 	ENTRYX(7483_dip,            TTL_7483_DIP,           "-")
+	ENTRYX(7485_dip,            TTL_7485_DIP,           "-")
 	ENTRYX(7490_dip,            TTL_7490_DIP,           "-")
 	ENTRYX(7493_dip,            TTL_7493_DIP,           "-")
 	ENTRYX(74107_dip,           TTL_74107_DIP,          "-")
 	ENTRYX(74123_dip,           TTL_74123_DIP,          "-")
 	ENTRYX(74153_dip,           TTL_74153_DIP,          "-")
+	ENTRYX(74161_dip,           TTL_74161_DIP,          "-")
+	ENTRYX(74165_dip,           TTL_74165_DIP,          "-")
+	ENTRYX(74166_dip,           TTL_74166_DIP,          "-")
+	ENTRYX(74174_dip,           TTL_74174_DIP,          "-")
 	ENTRYX(74175_dip,           TTL_74175_DIP,          "-")
 	ENTRYX(74192_dip,           TTL_74192_DIP,          "-")
 	ENTRYX(74193_dip,           TTL_74193_DIP,          "-")
+	ENTRYX(74194_dip,           TTL_74194_DIP,          "-")
 	ENTRYX(74279_dip,           TTL_74279_DIP,          "-")
+	ENTRYX(74365_dip,           TTL_74365_DIP,          "-")
 	ENTRYX(82S16_dip,           TTL_82S16_DIP,          "-")
+	ENTRYX(82S115_dip,          PROM_82S115_DIP,        "-")
+	ENTRYX(82S123_dip,          PROM_82S123_DIP,        "-")
+	ENTRYX(82S126_dip,          PROM_82S126_DIP,        "-")
 	ENTRYX(9602_dip,            TTL_9602_DIP,           "-")
 	ENTRYX(9310_dip,            TTL_9310_DIP,           "-")
 	ENTRYX(9312_dip,            TTL_9312_DIP,           "-")
 	ENTRYX(9316_dip,            TTL_9316_DIP,           "-")
+	ENTRYX(9322_dip,            TTL_9322_DIP,           "-")
+	ENTRYX(9334_dip,            TTL_9334_DIP,           "-")
+	ENTRYX(AM2847_dip,          TTL_AM2847_DIP,         "-")
 	ENTRYX(SN74LS629_dip,       SN74LS629_DIP,          "1.CAP1,2.CAP2")
 	ENTRYX(NE555_dip,           NE555_DIP,              "-")
 	ENTRYX(MM5837_dip,          MM5837_DIP,             "-")
diff --git a/src/lib/netlist/devices/net_lib.h b/src/lib/netlist/devices/net_lib.h
index b87526b..c9c0b6b 100644
--- a/src/lib/netlist/devices/net_lib.h
+++ b/src/lib/netlist/devices/net_lib.h
@@ -14,32 +14,52 @@
 #include "nl_base.h"
 #include "nld_system.h"
 
+#include "nld_2102A.h"
+#include "nld_2716.h"
 #include "nld_4020.h"
 #include "nld_4066.h"
 #include "nld_7448.h"
 #include "nld_7450.h"
+#include "nld_7473.h"
 #include "nld_7474.h"
+#include "nld_7475.h"
 #include "nld_7483.h"
+#include "nld_7485.h"
 #include "nld_7490.h"
 #include "nld_7493.h"
 #include "nld_74107.h"
 #include "nld_74123.h"
 #include "nld_74153.h"
+#include "nld_74161.h"
+#include "nld_74165.h"
+#include "nld_74166.h"
+#include "nld_74174.h"
 #include "nld_74175.h"
 #include "nld_74192.h"
 #include "nld_74193.h"
+#include "nld_74194.h"
 #include "nld_74279.h"
+#include "nld_74365.h"
 #include "nld_74ls629.h"
 #include "nld_82S16.h"
+#include "nld_82S115.h"
+#include "nld_82S123.h"
+#include "nld_82S126.h"
 #include "nld_9310.h"
 #include "nld_9312.h"
 #include "nld_9316.h"
+#include "nld_9322.h"
+
+#include "nld_am2847.h"
+#include "nld_dm9334.h"
 
 #include "nld_ne555.h"
 #include "nld_mm5837.h"
 
 #include "nld_r2r_dac.h"
 
+#include "nld_tristate.h"
+
 #include "nld_log.h"
 
 #include "macro/nlm_cd4xxx.h"
diff --git a/src/lib/netlist/devices/nld_2102A.cpp b/src/lib/netlist/devices/nld_2102A.cpp
new file mode 100644
index 0000000..da8ffc3
--- /dev/null
+++ b/src/lib/netlist/devices/nld_2102A.cpp
@@ -0,0 +1,103 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ * nld_2102A.cpp
+ *
+ */
+
+#include "nld_2102A.h"
+
+#define ADDR2BYTE(a)    ((a) >> 3)
+#define ADDR2BIT(a)     ((a) & 0x7)
+
+namespace netlist
+{
+	namespace devices
+	{
+	NETLIB_OBJECT(2102A)
+	{
+		NETLIB_CONSTRUCTOR(2102A)
+		, m_A(*this, {{"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9" }})
+		, m_CEQ(*this, "CEQ")
+		, m_RWQ(*this, "RWQ")
+		, m_DI(*this, "DI")
+		, m_DO(*this, "DO")
+		, m_ram(*this, "m_ram", 0)
+		, m_RAM(*this, "m_RAM", &m_ram[0])
+		{
+		}
+
+		NETLIB_RESETI();
+		NETLIB_UPDATEI();
+
+	protected:
+		object_array_t<logic_input_t, 10> m_A;
+		logic_input_t m_CEQ;
+		logic_input_t m_RWQ;
+		logic_input_t m_DI;
+
+		logic_output_t m_DO;
+
+		state_var<uint_fast8_t[128]> m_ram; // 1024x1 bits
+		param_ptr_t m_RAM;
+	};
+
+	NETLIB_OBJECT_DERIVED(2102A_dip, 2102A)
+	{
+		NETLIB_CONSTRUCTOR_DERIVED(2102A_dip, 2102A)
+		{
+			register_subalias("8",     m_A[0]);
+			register_subalias("4",     m_A[1]);
+			register_subalias("5",     m_A[2]);
+			register_subalias("6",     m_A[3]);
+			register_subalias("7",     m_A[4]);
+			register_subalias("2",     m_A[5]);
+			register_subalias("1",     m_A[6]);
+			register_subalias("16",    m_A[7]);
+			register_subalias("15",    m_A[8]);
+			register_subalias("14",    m_A[9]);
+
+			register_subalias("13",    m_CEQ);
+			register_subalias("3",     m_RWQ);
+
+			register_subalias("11",    m_DI);
+			register_subalias("12",    m_DO);
+		}
+	};
+
+	NETLIB_UPDATE(2102A)
+	{
+		netlist_time max_delay = NLTIME_FROM_NS(350);
+
+		if (!m_CEQ())
+		{
+			unsigned a = 0;
+			for (std::size_t i=0; i<10; i++)
+			{
+				a |= m_A[i]() << i;
+			}
+			const unsigned byte = ADDR2BYTE(a);
+			const unsigned bit = ADDR2BIT(a);
+
+			if (!m_RWQ())
+			{
+				m_ram[byte] &= ~(static_cast<uint_fast8_t>(1)      << bit);
+				m_ram[byte] |=  (static_cast<uint_fast8_t>(m_DI()) << bit);
+			}
+
+			m_DO.push((m_ram[byte] >> bit) & 1, max_delay);
+		}
+	}
+
+	NETLIB_RESET(2102A)
+	{
+		m_RAM.setTo(&m_ram[0]);
+		for (std::size_t i=0; i<128; i++)
+			m_ram[i] = 0;
+	}
+
+	NETLIB_DEVICE_IMPL(2102A)
+	NETLIB_DEVICE_IMPL(2102A_dip)
+
+	} //namespace devices
+} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_2102A.h b/src/lib/netlist/devices/nld_2102A.h
new file mode 100644
index 0000000..bec20f9
--- /dev/null
+++ b/src/lib/netlist/devices/nld_2102A.h
@@ -0,0 +1,48 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ * nld_2102A.h
+ *
+ *  2102: 1024 x 1-bit Static RAM
+ *
+ *          +--------------+
+ *       A6 |1     ++    16| A7
+ *       A5 |2           15| A8
+ *      RWQ |3           14| A9
+ *       A1 |4   82S16   13| CEQ
+ *       A2 |5           12| DO
+ *       A3 |6           11| DI
+ *       A4 |7           10| VCC
+ *       A0 |8            9| GND
+ *          +--------------+
+ *
+ *
+ *  Naming conventions follow Intel datasheet
+ *
+ */
+
+#ifndef NLD_2102A_H_
+#define NLD_2102A_H_
+
+#include "nl_setup.h"
+
+#define RAM_2102A(name, cCEQ, cA0, cA1, cA2, cA3, cA4, cA5, cA6, cA7, cA8, cA9, cRWQ, cDI)  \
+		NET_REGISTER_DEV(RAM_2102A, name)   \
+		NET_CONNECT(name, CEQ, cCEQ)    \
+		NET_CONNECT(name, A0,  cA0)     \
+		NET_CONNECT(name, A1,  cA1)     \
+		NET_CONNECT(name, A2,  cA2)     \
+		NET_CONNECT(name, A3,  cA3)     \
+		NET_CONNECT(name, A4,  cA4)     \
+		NET_CONNECT(name, A5,  cA5)     \
+		NET_CONNECT(name, A6,  cA6)     \
+		NET_CONNECT(name, A7,  cA7)     \
+		NET_CONNECT(name, A8,  cA8)     \
+		NET_CONNECT(name, A9,  cA9)     \
+		NET_CONNECT(name, RWQ, cRWQ)    \
+		NET_CONNECT(name, DI, cDI)
+
+#define RAM_2102A_DIP(name)                                 \
+		NET_REGISTER_DEV(RAM_2102A_DIP, name)
+
+#endif /* NLD_2102A_H_ */
diff --git a/src/lib/netlist/devices/nld_2716.cpp b/src/lib/netlist/devices/nld_2716.cpp
new file mode 100644
index 0000000..68cf4dc
--- /dev/null
+++ b/src/lib/netlist/devices/nld_2716.cpp
@@ -0,0 +1,101 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ * nld_2716.cpp
+ *
+ */
+
+#include "nld_2716.h"
+
+namespace netlist
+{
+	namespace devices
+	{
+	NETLIB_OBJECT(2716)
+	{
+		NETLIB_CONSTRUCTOR(2716)
+		, m_A(*this, {{ "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "A10" }})
+		, m_GQ(*this, "GQ")
+		, m_EPQ(*this, "EPQ")
+		, m_D(*this, {{ "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7" }})
+		, m_last_EPQ(*this, "m_last_EPQ", 1)
+		, m_ROM(*this, "m_ROM", nullptr)
+		{
+		}
+
+		NETLIB_UPDATEI();
+
+	protected:
+		object_array_t<logic_input_t, 11> m_A;
+		logic_input_t m_GQ;
+		logic_input_t m_EPQ;
+		object_array_t<logic_output_t, 8> m_D;
+
+		state_var<unsigned> m_last_EPQ;
+
+		param_ptr_t m_ROM; // 16 Kbits, used as 2 Kbit x 8
+	};
+
+	NETLIB_OBJECT_DERIVED(2716_dip, 2716)
+	{
+		NETLIB_CONSTRUCTOR_DERIVED(2716_dip, 2716)
+		{
+			register_subalias("8",     m_A[0]);
+			register_subalias("7",     m_A[1]);
+			register_subalias("6",     m_A[2]);
+			register_subalias("5",     m_A[3]);
+			register_subalias("4",     m_A[4]);
+			register_subalias("3",     m_A[5]);
+			register_subalias("2",     m_A[6]);
+			register_subalias("1",     m_A[7]);
+			register_subalias("23",    m_A[8]);
+			register_subalias("22",    m_A[9]);
+			register_subalias("19",    m_A[10]);
+
+			register_subalias("20",    m_GQ);
+			register_subalias("18",    m_EPQ);
+
+			register_subalias("9",     m_D[0]);
+			register_subalias("10",    m_D[1]);
+			register_subalias("11",    m_D[2]);
+			register_subalias("13",    m_D[3]);
+			register_subalias("14",    m_D[4]);
+			register_subalias("15",    m_D[5]);
+			register_subalias("16",    m_D[6]);
+			register_subalias("17",    m_D[7]);
+		}
+	};
+
+	// FIXME: timing!
+	NETLIB_UPDATE(2716)
+	{
+		unsigned d = 0xff;
+
+		netlist_time delay = NLTIME_FROM_NS(450);
+		if (!m_GQ() && !m_EPQ())
+		{
+			unsigned a = 0;
+			for (std::size_t i=0; i<11; i++)
+			a |= (m_A[i]() << i);
+
+			if (m_ROM() != nullptr)
+			{
+				d = ((std::uint_fast8_t*)(m_ROM()))[a];
+			}
+
+			if (m_last_EPQ)
+				delay = NLTIME_FROM_NS(120);
+		}
+
+		m_last_EPQ = m_EPQ();
+
+		// FIXME: Outputs are tristate. This needs to be properly implemented
+		for (std::size_t i=0; i<8; i++)
+			m_D[i].push((d >> i) & 1, delay);
+	}
+
+	NETLIB_DEVICE_IMPL(2716)
+	NETLIB_DEVICE_IMPL(2716_dip)
+
+	} //namespace devices
+} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_2716.h b/src/lib/netlist/devices/nld_2716.h
new file mode 100644
index 0000000..c96c726
--- /dev/null
+++ b/src/lib/netlist/devices/nld_2716.h
@@ -0,0 +1,52 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ * nld_82S126.h
+ *
+ *  2716: 16 Kbit (2Kb x 8) UV EPROM
+ *
+ *          +----------------+
+ *       A7 |1      ++     24| VCC
+ *       A6 |2             23| A8
+ *       A5 |3             22| A9
+ *       A4 |4     2716    21| VPP
+ *       A3 |5             20| GQ
+ *       A2 |6             19| A10
+ *       A1 |7             18| EPQ
+ *       A0 |8             17| D7
+ *       D0 |9             16| D6
+ *       D1 |10            15| D5
+ *       D2 |11            14| D4
+ *      VSS |12            13| D3
+ *          +----------------+
+ *
+ *
+ *  Naming conventions follow STMicro datasheet
+ *
+ */
+
+#ifndef NLD_2716_H_
+#define NLD_2716_H_
+
+#include "nl_setup.h"
+
+#define EPROM_2716(name, cGQ, cEPQ, cA0, cA1, cA2, cA3, cA4, cA5, cA6, cA7, cA8, cA9, cA10) \
+		NET_REGISTER_DEV(EPROM_2716, name) \
+		NET_CONNECT(name, GQ,  cGQ)     \
+		NET_CONNECT(name, EPQ, cEPQ)    \
+		NET_CONNECT(name, A0,  cA0)     \
+		NET_CONNECT(name, A1,  cA1)     \
+		NET_CONNECT(name, A2,  cA2)     \
+		NET_CONNECT(name, A3,  cA3)     \
+		NET_CONNECT(name, A4,  cA4)     \
+		NET_CONNECT(name, A5,  cA5)     \
+		NET_CONNECT(name, A6,  cA6)     \
+		NET_CONNECT(name, A7,  cA7)     \
+		NET_CONNECT(name, A8,  cA8)     \
+		NET_CONNECT(name, A9,  cA9)     \
+		NET_CONNECT(name, A10, cA10)
+
+#define EPROM_2716_DIP(name)                                 \
+		NET_REGISTER_DEV(EPROM_2716_DIP, name)
+
+#endif /* NLD_2716_H_ */
diff --git a/src/lib/netlist/devices/nld_4066.h b/src/lib/netlist/devices/nld_4066.h
index 570f9ec..fdaa76d 100644
--- a/src/lib/netlist/devices/nld_4066.h
+++ b/src/lib/netlist/devices/nld_4066.h
@@ -15,7 +15,7 @@
  *      VSS |7            8| INOUTC
  *          +--------------+
  *
- *  FIXME: These devices are slow (~125 ns). THis is currently not reflected
+ *  FIXME: These devices are slow (~125 ns). This is currently not reflected
  *
  *  Naming conventions follow National semiconductor datasheet
  *
diff --git a/src/lib/netlist/devices/nld_4316.cpp b/src/lib/netlist/devices/nld_4316.cpp
new file mode 100644
index 0000000..257ee0a
--- /dev/null
+++ b/src/lib/netlist/devices/nld_4316.cpp
@@ -0,0 +1,49 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/*
+ * nld_4316.c
+ *
+ */
+
+#include <devices/nlid_cmos.h>
+#include "analog/nld_twoterm.h"
+#include "nld_4316.h"
+
+namespace netlist { namespace devices {
+
+	NETLIB_OBJECT(CD4316_GATE)
+	{
+		NETLIB_CONSTRUCTOR(CD4316_GATE)
+		NETLIB_FAMILY("CD4XXX")
+		, m_supply(*this, "PS")
+		, m_R(*this, "R")
+		, m_S(*this, "S")
+		, m_E(*this, "E")
+		, m_base_r(*this, "BASER", 45.0)
+		{
+		}
+
+		NETLIB_RESETI() { }
+		NETLIB_UPDATEI();
+
+	public:
+		NETLIB_SUB(vdd_vss) m_supply;
+		NETLIB_SUB(R) m_R;
+
+		logic_input_t m_S, m_E;
+		param_double_t m_base_r;
+	};
+
+	NETLIB_UPDATE(CD4316_GATE)
+	{
+		m_R.update_dev();
+		if (m_S() && !m_E())
+			m_R.set_R(m_base_r());
+		else
+			m_R.set_R(NL_FCONST(1.0) / netlist().gmin());
+		m_R.m_P.schedule_after(NLTIME_FROM_NS(1));
+	}
+
+	NETLIB_DEVICE_IMPL(CD4316_GATE)
+
+} } // namesapce netlist::devices
diff --git a/src/lib/netlist/devices/nld_4316.h b/src/lib/netlist/devices/nld_4316.h
new file mode 100644
index 0000000..8d8ec4f
--- /dev/null
+++ b/src/lib/netlist/devices/nld_4316.h
@@ -0,0 +1,33 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/*
+ * nld_4136.h
+ *
+ *  CD4066: Quad Analog Switch with Level Translation
+ *
+ *          +--------------+
+ *       1Z |1     ++    16| VCC
+ *       1Y |2           15| 1S
+ *       2Y |3           14| 4S
+ *       2Z |4    4066   13| 4Z
+ *       2S |5           12| 4Y
+ *       3S |6           11| 3Y
+ *       /E |7           10| 3Z
+ *      GND |8            9| VEE
+ *          +--------------+
+ *
+ *  FIXME: These devices are slow (can be over 200 ns in HC types). This is currently not reflected
+ *
+ *  Naming conventions follow Texas Instruments datasheet
+ *
+ */
+
+#ifndef NLD_4316_H_
+#define NLD_4316_H_
+
+#include "nl_setup.h"
+
+#define CD4316_GATE(name)                                                       \
+		NET_REGISTER_DEV(CD4316_GATE, name)
+
+#endif /* NLD_4316_H_ */
diff --git a/src/lib/netlist/devices/nld_74107.cpp b/src/lib/netlist/devices/nld_74107.cpp
index a0ffcfc..a9006d5 100644
--- a/src/lib/netlist/devices/nld_74107.cpp
+++ b/src/lib/netlist/devices/nld_74107.cpp
@@ -11,6 +11,10 @@ namespace netlist
 {
 	namespace devices
 	{
+
+	static const netlist_time delay_107[2] = { NLTIME_FROM_NS(16), NLTIME_FROM_NS(25) };
+	static const netlist_time delay_107A[2] = { NLTIME_FROM_NS(15), NLTIME_FROM_NS(15) };
+
 	NETLIB_OBJECT(74107Asub)
 	{
 		NETLIB_CONSTRUCTOR(74107Asub)
@@ -20,6 +24,7 @@ namespace netlist
 		, m_Q1(*this, "m_Q1", 0)
 		, m_Q2(*this, "m_Q2", 0)
 		, m_F(*this, "m_F", 0)
+		, m_delay(delay_107A)
 		{
 		}
 
@@ -38,6 +43,8 @@ namespace netlist
 
 		void newstate(const netlist_sig_t state);
 
+		const netlist_time *m_delay;
+
 	};
 
 	NETLIB_OBJECT(74107A)
@@ -67,8 +74,10 @@ namespace netlist
 	NETLIB_OBJECT_DERIVED(74107, 74107A)
 	{
 	public:
-		NETLIB_CONSTRUCTOR_DERIVED(74107, 74107A) { }
-
+		NETLIB_CONSTRUCTOR_DERIVED(74107, 74107A)
+		{
+			m_sub.m_delay = delay_107;
+		}
 	};
 
 	NETLIB_OBJECT(74107_dip)
@@ -119,10 +128,8 @@ namespace netlist
 
 	inline void NETLIB_NAME(74107Asub)::newstate(const netlist_sig_t state)
 	{
-		const netlist_time delay[2] = { NLTIME_FROM_NS(25), NLTIME_FROM_NS(40) };
-
-		m_Q.push(state, delay[state]);
-		m_QQ.push(state ^ 1, delay[state ^ 1]);
+		m_Q.push(state, m_delay[state]);
+		m_QQ.push(state ^ 1, m_delay[state ^ 1]);
 	}
 
 	NETLIB_UPDATE(74107Asub)
diff --git a/src/lib/netlist/devices/nld_74107.h b/src/lib/netlist/devices/nld_74107.h
index ea73256..ed940f8 100644
--- a/src/lib/netlist/devices/nld_74107.h
+++ b/src/lib/netlist/devices/nld_74107.h
@@ -32,7 +32,9 @@
  *
  *          This is positive triggered, J and K
  *          are latched during clock high and
- *          transferred when CLK falls.
+ *          transferred when CLK falls. The
+ *          datasheet requires J and K to be
+ *          stable during clock high.
  *
  *          Function table 107A
  *
@@ -51,8 +53,11 @@
  *
  *  Naming conventions follow Texas instruments datasheet
  *
- *  FIXME: Currently, only the 107A is implemented.
- *         The 107 uses the same model.
+ *  TODO:  Currently, only the 107A is implemented.
+ *         The 107 uses the same model, but different timings.
+ *         The requirement that J and K must be stable during
+ *         clock high indicates that the chip may exhibit undefined
+ *         behaviour.
  *
  */
 
@@ -71,7 +76,7 @@
 #define TTL_74107(name, cCLK, cJ, cK, cCLRQ)                                    \
 		TTL_74107A(name, cCLK, cJ, cK, cCLRQ)
 
-#define TTL_74107_DIP(name)                                                     \
+#define TTL_74107_DIP(name)                             \
 		NET_REGISTER_DEV(TTL_74107_DIP, name)
 
 #endif /* NLD_74107_H_ */
diff --git a/src/lib/netlist/devices/nld_74161.cpp b/src/lib/netlist/devices/nld_74161.cpp
new file mode 100644
index 0000000..d6e31f3
--- /dev/null
+++ b/src/lib/netlist/devices/nld_74161.cpp
@@ -0,0 +1,133 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ * nld_74161.cpp
+ *
+ */
+
+#define MAXCNT 15
+
+#include "nld_74161.h"
+
+namespace netlist
+{
+	namespace devices
+	{
+	NETLIB_OBJECT(74161)
+	{
+		NETLIB_CONSTRUCTOR(74161)
+		, m_A(*this, "A")
+		, m_B(*this, "B")
+		, m_C(*this, "C")
+		, m_D(*this, "D")
+		, m_CLRQ(*this, "CLRQ")
+		, m_LOADQ(*this, "LOADQ")
+		, m_CLK(*this, "CLK")
+		, m_ENABLEP(*this, "ENABLEP")
+		, m_ENABLET(*this, "ENABLET")
+		, m_cnt(*this, "m_cnt", 0)
+		, m_last_CLK(*this, "m_last_CLK", 0)
+		, m_Q(*this, {{"QA", "QB", "QC", "QD"}})
+		, m_RCO(*this, "RCO")
+		{
+		}
+
+		NETLIB_RESETI();
+		NETLIB_UPDATEI();
+
+	protected:
+		logic_input_t m_A;
+		logic_input_t m_B;
+		logic_input_t m_C;
+		logic_input_t m_D;
+		logic_input_t m_CLRQ;
+		logic_input_t m_LOADQ;
+		logic_input_t m_CLK;
+		logic_input_t m_ENABLEP;
+		logic_input_t m_ENABLET;
+
+		state_var<unsigned> m_cnt;
+		state_var<unsigned> m_last_CLK;
+
+		object_array_t<logic_output_t, 4> m_Q;
+		logic_output_t m_RCO;
+	};
+
+	NETLIB_OBJECT_DERIVED(74161_dip, 74161)
+	{
+		NETLIB_CONSTRUCTOR_DERIVED(74161_dip, 74161)
+		{
+			register_subalias("1", m_CLRQ);
+			register_subalias("2", m_CLK);
+			register_subalias("3", m_A);
+			register_subalias("4", m_B);
+			register_subalias("5", m_C);
+			register_subalias("6", m_D);
+			register_subalias("7", m_ENABLEP);
+
+			register_subalias("9", m_LOADQ);
+			register_subalias("10", m_ENABLET);
+			register_subalias("11", m_Q[3]);
+			register_subalias("12", m_Q[2]);
+			register_subalias("13", m_Q[1]);
+			register_subalias("14", m_Q[0]);
+			register_subalias("15", m_RCO);
+
+		}
+	};
+
+	NETLIB_RESET(74161)
+	{
+		m_cnt = 0;
+		m_last_CLK = 0;
+	}
+
+	// FIXME: Timing
+	static const netlist_time delay[4] =
+	{
+			NLTIME_FROM_NS(40),
+			NLTIME_FROM_NS(40),
+			NLTIME_FROM_NS(40),
+			NLTIME_FROM_NS(40)
+	};
+
+	NETLIB_UPDATE(74161)
+	{
+		netlist_sig_t tRippleCarryOut = 0;
+		if (!m_CLRQ())
+		{
+			m_cnt = 0;
+		}
+		else if (m_CLK() && !m_last_CLK)
+		{
+			if (!m_LOADQ())
+			{
+				m_cnt = (m_D() << 3) | (m_C() << 2)
+						| (m_B() << 1) | (m_A() << 0);
+			}
+			else if (m_ENABLET() && m_ENABLEP())
+			{
+				m_cnt++;
+				if (m_cnt > MAXCNT)
+					m_cnt = 0;
+			}
+		}
+
+		if (m_ENABLET() && (m_cnt == MAXCNT))
+		{
+			tRippleCarryOut = 1;
+		}
+
+		m_last_CLK = m_CLK();
+
+		for (std::size_t i=0; i<4; i++)
+			m_Q[i].push((m_cnt >> i) & 1, delay[i]);
+
+		m_RCO.push(tRippleCarryOut, NLTIME_FROM_NS(20)); //FIXME
+	}
+
+	NETLIB_DEVICE_IMPL(74161)
+	NETLIB_DEVICE_IMPL(74161_dip)
+
+	} //namespace devices
+} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_74161.h b/src/lib/netlist/devices/nld_74161.h
new file mode 100644
index 0000000..1a6b6b2
--- /dev/null
+++ b/src/lib/netlist/devices/nld_74161.h
@@ -0,0 +1,45 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ * nld_74161.h
+ *
+ *  DM74161: Synchronous 4-Bit Binary Counter with Clock
+ *
+ *          +--------------+
+ *    CLEAR |1     ++    16| VCC
+ *      CLK |2           15| RCO
+ *        A |3           14| QA
+ *        B |4    74161  13| QB
+ *        C |5           12| QC
+ *        D |6           11| QD
+ *  ENABLEP |7           10| ENABLET
+ *      GND |8            9| LOAD
+ *          +--------------+
+ *
+ * RCO: Ripple carry output
+ *
+ *  Naming convention attempts to follow National Semiconductor datasheet
+ *
+ */
+
+#ifndef NLD_74161_H_
+#define NLD_74161_H_
+
+#include "nl_setup.h"
+
+#define TTL_74161(name, cA, cB, cC, cD, cCLRQ, cLOADQ, cCLK, cENABLEP, cENABLET)    \
+		NET_REGISTER_DEV(TTL_74161, name)   \
+		NET_CONNECT(name, A,       cA)      \
+		NET_CONNECT(name, B,       cB)      \
+		NET_CONNECT(name, C,       cC)      \
+		NET_CONNECT(name, D,       cD)      \
+		NET_CONNECT(name, CLRQ,   cCLRQ)    \
+		NET_CONNECT(name, LOADQ,   cLOADQ)  \
+		NET_CONNECT(name, CLK,     cCLK)    \
+		NET_CONNECT(name, ENABLEP, cENABLEP) \
+		NET_CONNECT(name, ENABLET, cENABLET)
+
+#define TTL_74161_DIP(name)                                                     \
+		NET_REGISTER_DEV(TTL_74161_DIP, name)
+
+#endif /* NLD_74161_H_ */
diff --git a/src/lib/netlist/devices/nld_74165.cpp b/src/lib/netlist/devices/nld_74165.cpp
new file mode 100644
index 0000000..bb26340
--- /dev/null
+++ b/src/lib/netlist/devices/nld_74165.cpp
@@ -0,0 +1,107 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ * nld_74165.cpp
+ *
+ */
+
+#include "nld_74165.h"
+
+namespace netlist
+{
+	namespace devices
+	{
+	NETLIB_OBJECT(74165)
+	{
+		NETLIB_CONSTRUCTOR(74165)
+		, m_DATA(*this, {{ "H", "G", "F", "E", "D", "C", "B", "A" }})
+		, m_SER(*this, "SER")
+		, m_SH_LDQ(*this, "SH_LDQ")
+		, m_CLK(*this, "CLK")
+		, m_CLKINH(*this, "CLKINH")
+		, m_QH(*this, "QH")
+		, m_QHQ(*this, "QHQ")
+		, m_shifter(*this, "m_shifter", 0)
+		, m_last_CLK(*this, "m_last_CLK", 0)
+		{
+		}
+
+		NETLIB_RESETI();
+		NETLIB_UPDATEI();
+
+	protected:
+		object_array_t<logic_input_t, 8> m_DATA;
+		logic_input_t m_SER;
+		logic_input_t m_SH_LDQ;
+		logic_input_t m_CLK;
+		logic_input_t m_CLKINH;
+		logic_output_t m_QH;
+		logic_output_t m_QHQ;
+
+		state_var<unsigned> m_shifter;
+		state_var<unsigned> m_last_CLK;
+	};
+
+	NETLIB_OBJECT_DERIVED(74165_dip, 74165)
+	{
+		NETLIB_CONSTRUCTOR_DERIVED(74165_dip, 74165)
+		{
+			register_subalias("1", m_SH_LDQ);
+			register_subalias("2", m_CLK);
+			register_subalias("3", m_DATA[4]);
+			register_subalias("4", m_DATA[5]);
+			register_subalias("5", m_DATA[6]);
+			register_subalias("6", m_DATA[7]);
+			register_subalias("7", m_QHQ);
+
+			register_subalias("9",  m_QH);
+			register_subalias("10", m_SER);
+			register_subalias("11", m_DATA[0]);
+			register_subalias("12", m_DATA[1]);
+			register_subalias("13", m_DATA[2]);
+			register_subalias("14", m_DATA[3]);
+			register_subalias("15", m_CLKINH);
+
+		}
+	};
+
+	NETLIB_RESET(74165)
+	{
+		m_shifter = 0;
+		m_last_CLK = 0;
+	}
+
+	// FIXME: Timing
+	NETLIB_UPDATE(74165)
+	{
+		netlist_sig_t old_qh = m_QH.net().Q();
+		netlist_sig_t qh = 0;
+
+		if (!m_SH_LDQ())
+		{
+			m_shifter = 0;
+			for (std::size_t i=0; i<8; i++)
+				m_shifter |= (m_DATA[i]() << i);
+		}
+		else if (!m_CLK() || m_CLKINH())
+		{
+			qh = old_qh;
+		}
+		else if (!m_last_CLK)
+		{
+			unsigned high_bit = m_SER() ? 0x80 : 0;
+			m_shifter = high_bit | (m_shifter >> 1);
+		}
+
+		qh = m_shifter & 1;
+
+		m_last_CLK = m_CLK();
+
+		m_QH.push(qh, NLTIME_FROM_NS(20)); // FIXME: Timing
+	}
+
+	NETLIB_DEVICE_IMPL(74165)
+	NETLIB_DEVICE_IMPL(74165_dip)
+
+	} //namespace devices
+} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_74165.h b/src/lib/netlist/devices/nld_74165.h
new file mode 100644
index 0000000..30970f5
--- /dev/null
+++ b/src/lib/netlist/devices/nld_74165.h
@@ -0,0 +1,50 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ * nld_74165.h
+ *
+ *  74165: Parallel-Load 8-Bit Shift Register
+ *
+ *          +--------------+
+ *   SH/LDQ |1     ++    16| VCC
+ *      CLK |2           15| CLKINH
+ *        E |3           14| D
+ *        F |4    74165  13| C
+ *        G |5           12| B
+ *        H |6           11| A
+ *      QHQ |7           10| SER
+ *      GND |8            9| QH
+ *          +--------------+
+ *
+ * SH/LDQ: Shift / !Load
+ * CLKINH: Clock Inhibit
+ * SER: Serial In
+ *
+ *  Naming convention attempts to follow NTE Electronics datasheet
+ *
+ */
+
+#ifndef NLD_74165_H_
+#define NLD_74165_H_
+
+#include "nl_setup.h"
+
+#define TTL_74165(name, cCLK, cCLKINH, cSH_LDQ, cSER, cA, cB, cC, cD, cE, cF, cG, cH)   \
+		NET_REGISTER_DEV(TTL_74165, name)   \
+		NET_CONNECT(name, CLK,    cCLK)     \
+		NET_CONNECT(name, CLKINH, cCLKINH)  \
+		NET_CONNECT(name, SH_LDQ, cSH_LDQ)  \
+		NET_CONNECT(name, SER,    cSER)     \
+		NET_CONNECT(name, A,      cA)       \
+		NET_CONNECT(name, B,      cB)       \
+		NET_CONNECT(name, C,      cC)       \
+		NET_CONNECT(name, D,      cD)       \
+		NET_CONNECT(name, E,      cE)       \
+		NET_CONNECT(name, F,      cF)       \
+		NET_CONNECT(name, G,      cG)       \
+		NET_CONNECT(name, H,      cH)
+
+#define TTL_74165_DIP(name)                                                     \
+		NET_REGISTER_DEV(TTL_74165_DIP, name)
+
+#endif /* NLD_74165_H_ */
diff --git a/src/lib/netlist/devices/nld_74166.cpp b/src/lib/netlist/devices/nld_74166.cpp
new file mode 100644
index 0000000..5cb7114
--- /dev/null
+++ b/src/lib/netlist/devices/nld_74166.cpp
@@ -0,0 +1,127 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ * nld_74166.cpp
+ *
+ */
+
+#include "nld_74166.h"
+
+namespace netlist
+{
+	namespace devices
+	{
+	NETLIB_OBJECT(74166)
+	{
+		NETLIB_CONSTRUCTOR(74166)
+		, m_DATA(*this, {{ "H", "G", "F", "E", "D", "C", "B", "A" }})
+		, m_SER(*this, "SER")
+		, m_CLRQ(*this, "CLRQ")
+		, m_SH_LDQ(*this, "SH_LDQ")
+		, m_CLK(*this, "CLK")
+		, m_CLKINH(*this, "CLKINH")
+		, m_QH(*this, "QH")
+		, m_shifter(*this, "m_shifter", 0)
+		, m_last_CLRQ(*this, "m_last_CLRQ", 0)
+		, m_last_CLK(*this, "m_last_CLK", 0)
+		{
+		}
+
+		NETLIB_RESETI();
+		NETLIB_UPDATEI();
+
+	protected:
+		object_array_t<logic_input_t, 8> m_DATA;
+		logic_input_t m_SER;
+		logic_input_t m_CLRQ;
+		logic_input_t m_SH_LDQ;
+		logic_input_t m_CLK;
+		logic_input_t m_CLKINH;
+		logic_output_t m_QH;
+
+		state_var<unsigned> m_shifter;
+		state_var<unsigned> m_last_CLRQ;
+		state_var<unsigned> m_last_CLK;
+	};
+
+	NETLIB_OBJECT_DERIVED(74166_dip, 74166)
+	{
+		NETLIB_CONSTRUCTOR_DERIVED(74166_dip, 74166)
+		{
+			register_subalias("1", m_SER);
+			register_subalias("2", m_DATA[7]);
+			register_subalias("3", m_DATA[6]);
+			register_subalias("4", m_DATA[5]);
+			register_subalias("5", m_DATA[4]);
+			register_subalias("6", m_CLKINH);
+			register_subalias("7", m_CLK);
+
+			register_subalias("9", m_CLRQ);
+			register_subalias("10", m_DATA[3]);
+			register_subalias("11", m_DATA[2]);
+			register_subalias("12", m_DATA[1]);
+			register_subalias("13", m_QH);
+			register_subalias("14", m_DATA[0]);
+			register_subalias("15", m_SH_LDQ);
+
+		}
+	};
+
+	NETLIB_RESET(74166)
+	{
+		m_shifter = 0;
+		m_last_CLRQ = 0;
+		m_last_CLK = 0;
+	}
+
+	NETLIB_UPDATE(74166)
+	{
+		netlist_sig_t old_qh = m_QH.net().Q();
+		netlist_sig_t qh = 0;
+
+		netlist_time delay = NLTIME_FROM_NS(26);
+		if (m_CLRQ())
+		{
+			bool clear_unset = !m_last_CLRQ();
+			if (clear_unset)
+			{
+				delay = NLTIME_FROM_NS(35);
+			}
+
+			if (!m_CLK() || m_CLKINH())
+			{
+				qh = old_qh;
+			}
+			else if (!m_last_CLK)
+			{
+				if (!m_SH_LDQ())
+				{
+					m_shifter = 0;
+					for (std::size_t i=0; i<8; i++)
+						m_shifter |= (m_DATA[i]() << i);
+				}
+				else
+				{
+					unsigned high_bit = m_SER() ? 0x80 : 0;
+					m_shifter = high_bit | (m_shifter >> 1);
+				}
+
+				qh = m_shifter & 1;
+				if (!qh && !clear_unset)
+				{
+					delay = NLTIME_FROM_NS(30);
+				}
+			}
+		}
+
+		m_last_CLRQ = m_CLRQ();
+		m_last_CLK = m_CLK();
+
+		m_QH.push(qh, delay); //FIXME
+	}
+
+	NETLIB_DEVICE_IMPL(74166)
+	NETLIB_DEVICE_IMPL(74166_dip)
+
+	} //namespace devices
+} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_74166.h b/src/lib/netlist/devices/nld_74166.h
new file mode 100644
index 0000000..bf5bbc8
--- /dev/null
+++ b/src/lib/netlist/devices/nld_74166.h
@@ -0,0 +1,51 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ * nld_74166.h
+ *
+ *  74166: Parallel-Load 8-Bit Shift Register
+ *
+ *          +--------------+
+ *      SER |1     ++    16| VCC
+ *        A |2           15| SH/LDQ
+ *        B |3           14| H
+ *        C |4    74166  13| QH
+ *        D |5           12| G
+ *   CLKINH |6           11| F
+ *      CLK |7           10| E
+ *      GND |8            9| CLRQ
+ *          +--------------+
+ *
+ * SH/LDQ: Shift / !Load
+ * CLKINH: Clock Inhibit
+ * SER: Serial In
+ *
+ *  Naming convention attempts to follow Texas Instruments datasheet
+ *
+ */
+
+#ifndef NLD_74166_H_
+#define NLD_74166_H_
+
+#include "nl_setup.h"
+
+#define TTL_74166(name, cCLK, cCLKINH, cSH_LDQ, cSER, cA, cB, cC, cD, cE, cF, cG, cH, cCLRQ)    \
+		NET_REGISTER_DEV(TTL_74166, name)   \
+		NET_CONNECT(name, CLK,    cCLK)     \
+		NET_CONNECT(name, CLKINH, cCLKINH)  \
+		NET_CONNECT(name, SH_LDQ, cSH_LDQ)  \
+		NET_CONNECT(name, SER,    cSER)     \
+		NET_CONNECT(name, A,      cA)       \
+		NET_CONNECT(name, B,      cB)       \
+		NET_CONNECT(name, C,      cC)       \
+		NET_CONNECT(name, D,      cD)       \
+		NET_CONNECT(name, E,      cE)       \
+		NET_CONNECT(name, F,      cF)       \
+		NET_CONNECT(name, G,      cG)       \
+		NET_CONNECT(name, H,      cH)       \
+		NET_CONNECT(name, CLRQ,   cCLRQ)
+
+#define TTL_74166_DIP(name)                                                     \
+		NET_REGISTER_DEV(TTL_74166_DIP, name)
+
+#endif /* NLD_74166_H_ */
diff --git a/src/lib/netlist/devices/nld_74174.cpp b/src/lib/netlist/devices/nld_74174.cpp
new file mode 100644
index 0000000..6469842
--- /dev/null
+++ b/src/lib/netlist/devices/nld_74174.cpp
@@ -0,0 +1,140 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * nld_74174.cpp
+ *
+ */
+
+#include "nld_74174.h"
+
+namespace netlist
+{
+	namespace devices
+	{
+	NETLIB_OBJECT(74174_sub)
+	{
+		NETLIB_CONSTRUCTOR(74174_sub)
+		, m_CLK(*this, "CLK")
+		, m_Q(*this, {{"Q1", "Q2", "Q3", "Q4", "Q5", "Q6"}})
+		, m_clrq(*this, "m_clr", 0)
+		, m_data(*this, "m_data", 0)
+		{
+		}
+
+		NETLIB_RESETI();
+		NETLIB_UPDATEI();
+
+	public:
+		logic_input_t m_CLK;
+		object_array_t<logic_output_t, 6> m_Q;
+
+		state_var<netlist_sig_t> m_clrq;
+		state_var<unsigned>      m_data;
+	};
+
+	NETLIB_OBJECT(74174)
+	{
+		NETLIB_CONSTRUCTOR(74174)
+		, m_sub(*this, "sub")
+		, m_D(*this, {{"D1", "D2", "D3", "D4", "D5", "D6"}})
+		, m_CLRQ(*this, "CLRQ")
+		{
+			register_subalias("CLK",   m_sub.m_CLK);
+
+			register_subalias("Q1",   m_sub.m_Q[0]);
+			register_subalias("Q2",   m_sub.m_Q[1]);
+			register_subalias("Q3",   m_sub.m_Q[2]);
+			register_subalias("Q4",   m_sub.m_Q[3]);
+			register_subalias("Q5",   m_sub.m_Q[4]);
+			register_subalias("Q6",   m_sub.m_Q[5]);
+		}
+
+		NETLIB_RESETI();
+		NETLIB_UPDATEI();
+
+	protected:
+		NETLIB_SUB(74174_sub) m_sub;
+		object_array_t<logic_input_t, 6> m_D;
+		logic_input_t m_CLRQ;
+	};
+
+	NETLIB_OBJECT_DERIVED(74174_dip, 74174)
+	{
+		NETLIB_CONSTRUCTOR_DERIVED(74174_dip, 74174)
+		{
+			register_subalias("1",  m_CLRQ);
+			register_subalias("9",  m_sub.m_CLK);
+
+			register_subalias("3",  m_D[0]);
+			register_subalias("2",  m_sub.m_Q[0]);
+
+			register_subalias("4",  m_D[1]);
+			register_subalias("5",  m_sub.m_Q[1]);
+
+			register_subalias("6",  m_D[2]);
+			register_subalias("7",  m_sub.m_Q[2]);
+
+			register_subalias("11", m_D[3]);
+			register_subalias("10", m_sub.m_Q[3]);
+
+			register_subalias("13", m_D[4]);
+			register_subalias("12", m_sub.m_Q[4]);
+
+			register_subalias("14", m_D[5]);
+			register_subalias("15", m_sub.m_Q[5]);
+		}
+	};
+
+	NETLIB_RESET(74174_sub)
+	{
+		m_CLK.set_state(logic_t::STATE_INP_LH);
+		m_clrq = 0;
+		m_data = 0xFF;
+	}
+
+	NETLIB_UPDATE(74174_sub)
+	{
+		if (m_clrq)
+		{
+			for (std::size_t i=0; i<6; i++)
+			{
+				netlist_sig_t d = (m_data >> i) & 1;
+				m_Q[i].push(d, NLTIME_FROM_NS(25));
+			}
+			m_CLK.inactivate();
+		}
+	}
+
+	NETLIB_UPDATE(74174)
+	{
+		uint_fast8_t d = 0;
+		for (std::size_t i=0; i<6; i++)
+		{
+			d |= (m_D[i]() << i);
+		}
+		m_sub.m_clrq = m_CLRQ();
+		if (!m_sub.m_clrq)
+		{
+			for (std::size_t i=0; i<6; i++)
+			{
+				m_sub.m_Q[i].push(0, NLTIME_FROM_NS(40));
+			}
+			m_sub.m_data = 0;
+		} else if (d != m_sub.m_data)
+		{
+			m_sub.m_data = d;
+			m_sub.m_CLK.activate_lh();
+		}
+	}
+
+
+	NETLIB_RESET(74174)
+	{
+		//m_sub.do_reset();
+	}
+
+	NETLIB_DEVICE_IMPL(74174)
+	NETLIB_DEVICE_IMPL(74174_dip)
+
+	} //namespace devices
+} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_74174.h b/src/lib/netlist/devices/nld_74174.h
new file mode 100644
index 0000000..43125b6
--- /dev/null
+++ b/src/lib/netlist/devices/nld_74174.h
@@ -0,0 +1,56 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * nld_74174.h
+ *
+ *  DM74174: Hex D Flip-Flops with Clear
+ *
+ *          +--------------+
+ *      CLR |1     ++    16| VCC
+ *       Q1 |2           15| Q6
+ *       D1 |3           14| D6
+ *       D2 |4   74174   13| D5
+ *       Q2 |5           12| Q5
+ *       D3 |6           11| D4
+ *       Q3 |7           10| Q4
+ *      GND |8            9| CLK
+ *          +--------------+
+ *
+ *          +-----+-----+---++---+-----+
+ *          | CLR | CLK | D || Q | QQ  |
+ *          +=====+=====+===++===+=====+
+ *          |  0  |  X  | X || 0 |  1  |
+ *          |  1  |  R  | 1 || 1 |  0  |
+ *          |  1  |  R  | 0 || 0 |  1  |
+ *          |  1  |  0  | X || Q0| Q0Q |
+ *          +-----+-----+---++---+-----+
+ *
+ *   Q0 The output logic level of Q before the indicated input conditions were established
+ *
+ *  R:  0 -> 1
+ *
+ *  Naming conventions follow National Semiconductor datasheet
+ *
+ */
+
+#ifndef NLD_74174_H_
+#define NLD_74174_H_
+
+#include "nl_setup.h"
+
+#define TTL_74174(name, cCLK, cD1, cD2, cD3, cD4, cD5, cD6, cCLRQ)  \
+		NET_REGISTER_DEV(TTL_74174, name)   \
+		NET_CONNECT(name, CLK,  cCLK)       \
+		NET_CONNECT(name, D1,   cD1)        \
+		NET_CONNECT(name, D2,   cD2)        \
+		NET_CONNECT(name, D3,   cD3)        \
+		NET_CONNECT(name, D4,   cD4)        \
+		NET_CONNECT(name, D5,   cD5)        \
+		NET_CONNECT(name, D6,   cD6)        \
+		NET_CONNECT(name, CLRQ, cCLRQ)
+
+#define TTL_74174_DIP(name)                                 \
+		NET_REGISTER_DEV(TTL_74174_DIP, name)
+
+
+#endif /* NLD_74174_H_ */
diff --git a/src/lib/netlist/devices/nld_74175.h b/src/lib/netlist/devices/nld_74175.h
index 8b08060..27dd01a 100644
--- a/src/lib/netlist/devices/nld_74175.h
+++ b/src/lib/netlist/devices/nld_74175.h
@@ -38,8 +38,15 @@
 
 #include "nl_setup.h"
 
-#define TTL_74175(name)                                     \
-		NET_REGISTER_DEV(TTL_74175, name)
+#define TTL_74175(name, cCLK, cD1, cD2, cD3, cD4, cCLRQ)    \
+		NET_REGISTER_DEV(TTL_74175, name)   \
+		NET_CONNECT(name, CLK,  cCLK)   \
+		NET_CONNECT(name, D1,   cD1)    \
+		NET_CONNECT(name, D2,   cD2)    \
+		NET_CONNECT(name, D3,   cD3)    \
+		NET_CONNECT(name, D4,   cD4)    \
+		NET_CONNECT(name, CLRQ, cCLRQ)
+
 #define TTL_74175_DIP(name)                                 \
 		NET_REGISTER_DEV(TTL_74175_DIP, name)
 
diff --git a/src/lib/netlist/devices/nld_74192.h b/src/lib/netlist/devices/nld_74192.h
index fc57780..8c82006 100644
--- a/src/lib/netlist/devices/nld_74192.h
+++ b/src/lib/netlist/devices/nld_74192.h
@@ -31,8 +31,16 @@
 
 #include "nl_setup.h"
 
-#define TTL_74192(name)                                                         \
-		NET_REGISTER_DEV(TTL_74192, name)
+#define TTL_74192(name, cA, cB, cC, cD, cCLEAR, cLOADQ, cCU, cCD)               \
+		NET_REGISTER_DEV(TTL_74192, name)   \
+		NET_CONNECT(name, A,     cA)        \
+		NET_CONNECT(name, B,     cB)        \
+		NET_CONNECT(name, C,     cC)        \
+		NET_CONNECT(name, D,     cD)        \
+		NET_CONNECT(name, CLEAR, cCLEAR)    \
+		NET_CONNECT(name, LOADQ, cLOADQ)    \
+		NET_CONNECT(name, CU,    cCU)       \
+		NET_CONNECT(name, CD,    cCD)
 
 #define TTL_74192_DIP(name)                                                     \
 		NET_REGISTER_DEV(TTL_74192_DIP, name)
diff --git a/src/lib/netlist/devices/nld_74193.h b/src/lib/netlist/devices/nld_74193.h
index fa2b812..53b6165 100644
--- a/src/lib/netlist/devices/nld_74193.h
+++ b/src/lib/netlist/devices/nld_74193.h
@@ -28,8 +28,16 @@
 
 #include "nl_setup.h"
 
-#define TTL_74193(name)                                                         \
-		NET_REGISTER_DEV(TTL_74193, name)
+#define TTL_74193(name, cA, cB, cC, cD, cCLEAR, cLOADQ, cCU, cCD)   \
+		NET_REGISTER_DEV(TTL_74193, name)   \
+		NET_CONNECT(name, A,     cA)    \
+		NET_CONNECT(name, B,     cB)    \
+		NET_CONNECT(name, C,     cC)    \
+		NET_CONNECT(name, D,     cD)    \
+		NET_CONNECT(name, CLEAR, cCLEAR) \
+		NET_CONNECT(name, LOADQ, cLOADQ) \
+		NET_CONNECT(name, CU,    cCU)   \
+		NET_CONNECT(name, CD,    cCD)
 
 #define TTL_74193_DIP(name)                                                     \
 		NET_REGISTER_DEV(TTL_74193_DIP, name)
diff --git a/src/lib/netlist/devices/nld_74194.cpp b/src/lib/netlist/devices/nld_74194.cpp
new file mode 100644
index 0000000..e951e35
--- /dev/null
+++ b/src/lib/netlist/devices/nld_74194.cpp
@@ -0,0 +1,122 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ * nld_74194.cpp
+ *
+ */
+
+#include "nld_74194.h"
+
+namespace netlist
+{
+	namespace devices
+	{
+	NETLIB_OBJECT(74194)
+	{
+		NETLIB_CONSTRUCTOR(74194)
+		, m_DATA(*this, {{"D", "C", "B", "A"}})
+		, m_SLIN(*this, "SLIN")
+		, m_SRIN(*this, "SRIN")
+		, m_CLK(*this, "CLK")
+		, m_S0(*this, "S0")
+		, m_S1(*this, "S1")
+		, m_CLRQ(*this, "CLRQ")
+		, m_Q(*this, {{"QD", "QC", "QB", "QA"}})
+		, m_last_CLK(*this, "m_last_CLK", 0)
+		, m_last_Q(*this, "m_last_Q", 0)
+		{
+		}
+
+		NETLIB_RESETI();
+		NETLIB_UPDATEI();
+
+	protected:
+		object_array_t<logic_input_t, 4> m_DATA;
+		logic_input_t m_SLIN;
+		logic_input_t m_SRIN;
+		logic_input_t m_CLK;
+		logic_input_t m_S0;
+		logic_input_t m_S1;
+		logic_input_t m_CLRQ;
+		object_array_t<logic_output_t, 4> m_Q;
+
+		state_var<unsigned> m_last_CLK;
+		state_var<unsigned> m_last_Q;
+	};
+
+	NETLIB_OBJECT_DERIVED(74194_dip, 74194)
+	{
+		NETLIB_CONSTRUCTOR_DERIVED(74194_dip, 74194)
+		{
+			register_subalias("1", m_CLRQ);
+			register_subalias("2", m_SRIN);
+			register_subalias("3", m_DATA[3]);
+			register_subalias("4", m_DATA[2]);
+			register_subalias("5", m_DATA[1]);
+			register_subalias("6", m_DATA[0]);
+			register_subalias("7", m_SLIN);
+
+			register_subalias("9",  m_S0);
+			register_subalias("10", m_S1);
+			register_subalias("11", m_CLK);
+			register_subalias("12", m_Q[0]);
+			register_subalias("13", m_Q[1]);
+			register_subalias("14", m_Q[2]);
+			register_subalias("15", m_Q[3]);
+
+		}
+	};
+
+	NETLIB_RESET(74194)
+	{
+		m_last_CLK = 0;
+		m_last_Q = 0;
+	}
+
+	// FIXME: Timing
+	NETLIB_UPDATE(74194)
+	{
+		unsigned q = m_last_Q;
+
+		if (!m_CLRQ())
+		{
+			q = 0;
+		}
+		else
+		{
+			if (!m_last_CLK && m_CLK())
+			{
+				unsigned s = (m_S1() << 1) | m_S0();
+				switch (s)
+				{
+					case 0: // LL: Keep old value
+						break;
+					case 1: // LH: Shift right
+						q >>= 1;
+						q |= m_SRIN() ? 8 : 0;
+						break;
+					case 2:
+						q <<= 1;
+						q |= m_SLIN() ? 1 : 0;
+						break;
+					case 3:
+						q = 0;
+						for (std::size_t i=0; i<4; i++)
+							q |= m_DATA[i]() << i;
+						break;
+				}
+			}
+		}
+
+		m_last_Q = q;
+		m_last_CLK = m_CLK();
+
+		for (std::size_t i=0; i<4; i++)
+			m_Q[i].push((q >> i) & 1, NLTIME_FROM_NS(26)); // FIXME: Timing
+	}
+
+	NETLIB_DEVICE_IMPL(74194)
+	NETLIB_DEVICE_IMPL(74194_dip)
+
+	} //namespace devices
+} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_74194.h b/src/lib/netlist/devices/nld_74194.h
new file mode 100644
index 0000000..3207495
--- /dev/null
+++ b/src/lib/netlist/devices/nld_74194.h
@@ -0,0 +1,47 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ * nld_74194.h
+ *
+ *  74194: Parallel-Load 8-Bit Shift Register
+ *
+ *          +--------------+
+ *     CLRQ |1     ++    16| VCC
+ *     SRIN |2           15| QA
+ *        A |3           14| QB
+ *        B |4    74194  13| QC
+ *        C |5           12| QD
+ *        D |6           11| CLK
+ *     SLIN |7           10| S1
+ *      GND |8            9| S0
+ *          +--------------+
+ *
+ * CLR: Clear
+ * SRIN: Shift Right Serial Input
+ * SLIN: Shift Left Serial Input
+ * CLK: Clock
+ *
+ */
+
+#ifndef NLD_74194_H_
+#define NLD_74194_H_
+
+#include "nl_setup.h"
+
+#define TTL_74194(name, cCLK, cS0, cS1, cSRIN, cA, cB, cC, cD, cSLIN, cCLRQ)    \
+		NET_REGISTER_DEV(TTL_74194, name)   \
+		NET_CONNECT(name, CLK,  cCLK)   \
+		NET_CONNECT(name, S0,   cS0)    \
+		NET_CONNECT(name, S1,   cC1)    \
+		NET_CONNECT(name, SRIN, cSRIN)  \
+		NET_CONNECT(name, A,    cA)     \
+		NET_CONNECT(name, B,    cB)     \
+		NET_CONNECT(name, C,    cC)     \
+		NET_CONNECT(name, D,    cD)     \
+		NET_CONNECT(name, SLIN, cSLIN)  \
+		NET_CONNECT(name, CLRQ, cCLRQ)
+
+#define TTL_74194_DIP(name)                                                     \
+		NET_REGISTER_DEV(TTL_74194_DIP, name)
+
+#endif /* NLD_74194_H_ */
diff --git a/src/lib/netlist/devices/nld_74365.cpp b/src/lib/netlist/devices/nld_74365.cpp
new file mode 100644
index 0000000..34eafb0
--- /dev/null
+++ b/src/lib/netlist/devices/nld_74365.cpp
@@ -0,0 +1,74 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ * nld_74365.cpp
+ *
+ */
+
+#include "nld_74365.h"
+
+namespace netlist
+{
+	namespace devices
+	{
+	NETLIB_OBJECT(74365)
+	{
+		NETLIB_CONSTRUCTOR(74365)
+		, m_G1Q(*this, "G1Q")
+		, m_G2Q(*this, "G2Q")
+		, m_A(*this, {{ "A1", "A2", "A3", "A4", "A5", "A6" }})
+		, m_Y(*this, {{ "Y1", "Y2", "Y3", "Y4", "Y5", "Y6" }})
+		{
+		}
+
+		NETLIB_UPDATEI();
+
+	protected:
+		logic_input_t m_G1Q;
+		logic_input_t m_G2Q;
+		object_array_t<logic_input_t, 6> m_A;
+		object_array_t<logic_output_t, 6> m_Y;
+	};
+
+	NETLIB_OBJECT_DERIVED(74365_dip, 74365)
+	{
+		NETLIB_CONSTRUCTOR_DERIVED(74365_dip, 74365)
+		{
+			register_subalias("1", m_G1Q);
+			register_subalias("2", m_A[0]);
+			register_subalias("3", m_Y[0]);
+			register_subalias("4", m_A[1]);
+			register_subalias("5", m_Y[1]);
+			register_subalias("6", m_A[2]);
+			register_subalias("7", m_Y[2]);
+
+			register_subalias("9",  m_A[3]);
+			register_subalias("10", m_Y[3]);
+			register_subalias("11", m_A[4]);
+			register_subalias("12", m_Y[4]);
+			register_subalias("13", m_A[5]);
+			register_subalias("14", m_Y[5]);
+			register_subalias("15", m_G2Q);
+
+		}
+	};
+
+	NETLIB_UPDATE(74365)
+	{
+		if (!m_G1Q() && !m_G2Q())
+		{
+			for (std::size_t i=0; i<6; i++)
+				m_Y[i].push(m_A[i](), NLTIME_FROM_NS(20)); // FIXME: Correct timing
+		}
+		else
+		{
+			for (std::size_t i=0; i<6; i++)
+				m_Y[i].push(0, NLTIME_FROM_NS(20)); // FIXME: Correct timing
+		}
+	}
+
+	NETLIB_DEVICE_IMPL(74365)
+	NETLIB_DEVICE_IMPL(74365_dip)
+
+	} //namespace devices
+} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_74365.h b/src/lib/netlist/devices/nld_74365.h
new file mode 100644
index 0000000..2a7fb23
--- /dev/null
+++ b/src/lib/netlist/devices/nld_74365.h
@@ -0,0 +1,44 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ * nld_74365.h
+ *
+ *  SN74365: Hex Bus Driver with 3-State Outputs
+ *
+ *          +--------------+
+ *      G1Q |1     ++    16| VCC
+ *       A1 |2           15| G2Q
+ *       Y1 |3           14| A6
+ *       A2 |4    74365  13| Y6
+ *       Y2 |5           12| A5
+ *       A3 |6           11| Y5
+ *       Y3 |7           10| A4
+ *      GND |8            9| Y4
+ *          +--------------+
+ *
+ *  Naming conventions follow Texas Instruments datasheet
+ *
+ *  Note: Currently the netlist system does not support proper tristate output, so this
+ *        is not a "real" bus driver, it simply outputs 0 if the chip is not enabled.
+ */
+
+#ifndef NLD_74365_H_
+#define NLD_74365_H_
+
+#include "nl_setup.h"
+
+#define TTL_74365(name, cG1Q, cG2Q, cA1, cA2, cA3, cA4, cA5, cA6)   \
+		NET_REGISTER_DEV(TTL_74365, name)   \
+		NET_CONNECT(name, G1Q,   cG1Q)  \
+		NET_CONNECT(name, G2Q,   cG2Q)  \
+		NET_CONNECT(name, A1,    cA1)   \
+		NET_CONNECT(name, A2,    cA2)   \
+		NET_CONNECT(name, A3,    cA3)   \
+		NET_CONNECT(name, A4,    cA4)   \
+		NET_CONNECT(name, A5,    cA5)   \
+		NET_CONNECT(name, A6,    cA6)
+
+#define TTL_74365_DIP(name)                                                     \
+		NET_REGISTER_DEV(TTL_74365_DIP, name)
+
+#endif /* NLD_74365_H_ */
diff --git a/src/lib/netlist/devices/nld_7473.cpp b/src/lib/netlist/devices/nld_7473.cpp
new file mode 100644
index 0000000..fc73b97
--- /dev/null
+++ b/src/lib/netlist/devices/nld_7473.cpp
@@ -0,0 +1,150 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * nld_7473.c
+ *
+ */
+
+#include "nld_7473.h"
+
+namespace netlist
+{
+	namespace devices
+	{
+	NETLIB_OBJECT(7473)
+	{
+		NETLIB_CONSTRUCTOR(7473)
+		, m_CLK(*this, "CLK")
+		, m_J(*this, "J")
+		, m_K(*this, "K")
+		, m_CLRQ(*this, "CLRQ")
+		, m_last_CLK(*this, "m_last_CLK", 0)
+		, m_q(*this, "m_q", 0)
+		, m_Q(*this, "Q")
+		, m_QQ(*this, "QQ")
+		{
+		}
+
+		NETLIB_RESETI();
+		NETLIB_UPDATEI();
+
+	public:
+		logic_input_t m_CLK;
+		logic_input_t m_J;
+		logic_input_t m_K;
+		logic_input_t m_CLRQ;
+
+		state_var<unsigned> m_last_CLK;
+		state_var<unsigned> m_q;
+
+		logic_output_t m_Q;
+		logic_output_t m_QQ;
+	};
+
+	NETLIB_OBJECT_DERIVED(7473A, 7473)
+	{
+	public:
+		NETLIB_CONSTRUCTOR_DERIVED(7473A, 7473) { }
+
+	};
+
+	NETLIB_OBJECT(7473_dip)
+	{
+		NETLIB_CONSTRUCTOR(7473_dip)
+		, m_1(*this, "1")
+		, m_2(*this, "2")
+		{
+			register_subalias("1", m_1.m_CLK);
+			register_subalias("2", m_1.m_CLRQ);
+			register_subalias("3", m_1.m_K);
+			//register_subalias("4", ); ==> VCC
+			register_subalias("5", m_2.m_CLK);
+			register_subalias("6", m_2.m_CLRQ);
+			register_subalias("7", m_2.m_J);
+
+			register_subalias("8", m_2.m_QQ);
+			register_subalias("9", m_2.m_Q);
+			register_subalias("10", m_2.m_K);
+			//register_subalias("11", ); ==> VCC
+			register_subalias("12", m_2.m_Q);
+			register_subalias("13", m_1.m_QQ);
+			register_subalias("14", m_1.m_J);
+		}
+
+	private:
+		NETLIB_SUB(7473) m_1;
+		NETLIB_SUB(7473) m_2;
+	};
+
+	NETLIB_OBJECT(7473A_dip)
+	{
+		NETLIB_CONSTRUCTOR(7473A_dip)
+		, m_1(*this, "1")
+		, m_2(*this, "2")
+		{
+			register_subalias("1", m_1.m_CLK);
+			register_subalias("2", m_1.m_CLRQ);
+			register_subalias("3", m_1.m_K);
+			//register_subalias("4", ); ==> VCC
+			register_subalias("5", m_2.m_CLK);
+			register_subalias("6", m_2.m_CLRQ);
+			register_subalias("7", m_2.m_J);
+
+			register_subalias("8", m_2.m_QQ);
+			register_subalias("9", m_2.m_Q);
+			register_subalias("10", m_2.m_K);
+			//register_subalias("11", ); ==> VCC
+			register_subalias("12", m_2.m_Q);
+			register_subalias("13", m_1.m_QQ);
+			register_subalias("14", m_1.m_J);
+		}
+
+	private:
+		NETLIB_SUB(7473A) m_1;
+		NETLIB_SUB(7473A) m_2;
+	};
+
+	NETLIB_RESET(7473)
+	{
+		m_last_CLK = 0;
+	}
+
+	NETLIB_UPDATE(7473)
+	{
+		const auto JK = (m_J() << 1) | m_K();
+
+		if (m_CLRQ())
+		{
+			if (!m_CLK() && m_last_CLK)
+			{
+				switch (JK)
+				{
+					case 1:             // (!m_J) & m_K))
+						m_q = 0;
+						break;
+					case 2:             // (m_J) & !m_K))
+						m_q = 1;
+						break;
+					case 3:             // (m_J) & m_K))
+						m_q ^= 1;
+						break;
+					default:
+					case 0:
+						break;
+				}
+			}
+		}
+
+		m_last_CLK = m_CLK();
+
+		m_Q.push(m_q, NLTIME_FROM_NS(20)); // FIXME: timing
+		m_QQ.push(m_q ^ 1, NLTIME_FROM_NS(20)); // FIXME: timing
+	}
+
+	NETLIB_DEVICE_IMPL(7473)
+	NETLIB_DEVICE_IMPL(7473A)
+	NETLIB_DEVICE_IMPL(7473_dip)
+	NETLIB_DEVICE_IMPL(7473A_dip)
+
+	} //namespace devices
+} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_74107.h b/src/lib/netlist/devices/nld_7473.h
similarity index 50%
copy from src/lib/netlist/devices/nld_74107.h
copy to src/lib/netlist/devices/nld_7473.h
index ea73256..344e768 100644
--- a/src/lib/netlist/devices/nld_74107.h
+++ b/src/lib/netlist/devices/nld_7473.h
@@ -1,22 +1,23 @@
 // license:GPL-2.0+
 // copyright-holders:Couriersud
 /*
- * nld_74107.h
+ * nld_7473.h
  *
- *  DM74107: DUAL J-K FLIP-FLOPS WITH CLEAR
+ *  7473: Dual Master-Slave J-K Flip-Flops with Clear and Complementary Outputs
+ *  7473A: Dual Negative-Edge-Triggered Master-Slave J-K Flip-Flops with Clear and Complementary Outputs
  *
- *          +--------------+
- *       1J |1     ++    14| VCC
- *      1QQ |2           13| 1CLRQ
- *       1Q |3           12| 1CLK
- *       1K |4    74107  11| 2K
- *       2Q |5           10| 2CLRQ
- *      2QQ |6            9| 2CLK
- *      GND |7            8| 2J
- *          +--------------+
+ *          +----------+
+ *     1CLK |1   ++  14| 1J
+ *    1CLRQ |2       13| 1QQ
+ *       1K |3       12| 1Q
+ *      VCC |4  7473 11| GND
+ *     2CLK |5       10| 2K
+ *    2CLRQ |6        9| 2Q
+ *       2J |7        8| 2QQ
+ *          +----------+
  *
  *
- *          Function table 107
+ *          Function table 73
  *
  *          +-----+-----+-----+---++---+-----+
  *          | CLRQ| CLK |  J  | K || Q | QQ  |
@@ -34,7 +35,7 @@
  *          are latched during clock high and
  *          transferred when CLK falls.
  *
- *          Function table 107A
+ *          Function table 73A
  *
  *          +-----+-----+-----+---++---+-----+
  *          | CLRQ| CLK |  J  | K || Q | QQ  |
@@ -47,31 +48,35 @@
  *          |  1  |  1  |  X  | X || Q0| Q0Q |
  *          +-----+-----+-----+---++---+-----+
  *
- *          THe 107A is negative triggered.
+ *          THe 73A is negative triggered.
  *
  *  Naming conventions follow Texas instruments datasheet
  *
- *  FIXME: Currently, only the 107A is implemented.
- *         The 107 uses the same model.
+ *  FIXME: Currently, only the 73 is implemented.
+ *         The 73A uses the same model.
  *
  */
 
-#ifndef NLD_74107_H_
-#define NLD_74107_H_
+#ifndef NLD_7473_H_
+#define NLD_7473_H_
 
 #include "nl_setup.h"
 
-#define TTL_74107A(name, cCLK, cJ, cK, cCLRQ)                                   \
-		NET_REGISTER_DEV(TTL_74107A, name)                                      \
-		NET_CONNECT(name, CLK, cCLK)                                            \
-		NET_CONNECT(name, J, cJ)                                                \
-		NET_CONNECT(name, K, cK)                                                \
+#define TTL_7473(name, cCLK, cJ, cK, cCLRQ) \
+		NET_REGISTER_DEV(TTL_7473, name)        \
+		NET_CONNECT(name, CLK, cCLK)            \
+		NET_CONNECT(name, J, cJ)                \
+		NET_CONNECT(name, K, cK)                \
 		NET_CONNECT(name, CLRQ, cCLRQ)
 
-#define TTL_74107(name, cCLK, cJ, cK, cCLRQ)                                    \
-		TTL_74107A(name, cCLK, cJ, cK, cCLRQ)
+#define TTL_7473A(name, cCLK, cJ, cK, cCLRQ)        \
+		TTL_7473(name, cCLK, cJ, cK, cCLRQ)
 
-#define TTL_74107_DIP(name)                                                     \
-		NET_REGISTER_DEV(TTL_74107_DIP, name)
+#define TTL_7473_DIP(name)                      \
+		NET_REGISTER_DEV(TTL_7473_DIP, name)
 
-#endif /* NLD_74107_H_ */
+
+#define TTL_7473A_DIP(name)                     \
+		NET_REGISTER_DEV(TTL_7473A_DIP, name)
+
+#endif /* NLD_7473_H_ */
diff --git a/src/lib/netlist/devices/nld_7475.cpp b/src/lib/netlist/devices/nld_7475.cpp
new file mode 100644
index 0000000..3c26c1c
--- /dev/null
+++ b/src/lib/netlist/devices/nld_7475.cpp
@@ -0,0 +1,156 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ * nld_7475.cpp
+ *
+ * TODO: Correct timing for clock-induced state changes, rather than assuming timing is always due to data-induced state changes
+ */
+
+#include "nld_7475.h"
+
+namespace netlist
+{
+	namespace devices
+	{
+	NETLIB_OBJECT(7477)
+	{
+		NETLIB_CONSTRUCTOR(7477)
+		, m_C1C2(*this, "C1C2")
+		, m_C3C4(*this, "C3C4")
+		, m_last_Q(*this, "m_last_Q", 0)
+		, m_D(*this, {{"D1", "D2", "D3", "D4"}})
+		, m_Q(*this, {{"Q1", "Q2", "Q3", "Q4"}})
+		{
+			register_subalias("Q1", m_Q[0]);
+		}
+
+		NETLIB_RESETI();
+		NETLIB_UPDATEI();
+
+		void update_outputs(std::size_t start, std::size_t end);
+
+	public:
+		logic_input_t m_C1C2;
+		logic_input_t m_C3C4;
+		state_var<unsigned> m_last_Q;
+		object_array_t<logic_input_t, 4> m_D;
+		object_array_t<logic_output_t, 4> m_Q;
+	};
+
+	NETLIB_OBJECT_DERIVED(7475, 7477)
+	{
+		NETLIB_CONSTRUCTOR_DERIVED(7475, 7477)
+		, m_QQ(*this, {{"QQ1", "QQ2", "QQ3", "QQ4"}})
+		{
+		}
+
+		NETLIB_UPDATEI();
+
+	public:
+		object_array_t<logic_output_t, 4> m_QQ;
+	};
+
+	NETLIB_OBJECT_DERIVED(7475_dip, 7475)
+	{
+		NETLIB_CONSTRUCTOR_DERIVED(7475_dip, 7475)
+		{
+			register_subalias("1", m_QQ[0]);
+			register_subalias("2", m_D[0]);
+			register_subalias("3", m_D[1]);
+			register_subalias("4", m_C3C4);
+			//register_subalias("5", ); ==> VCC
+			register_subalias("6", m_D[2]);
+			register_subalias("7", m_D[3]);
+			register_subalias("8", m_QQ[3]);
+
+			register_subalias("9",  m_Q[3]);
+			register_subalias("10", m_Q[2]);
+			register_subalias("11", m_QQ[2]);
+			//register_subalias("12", ); ==> GND
+			register_subalias("13", m_C1C2);
+			register_subalias("14", m_QQ[1]);
+			register_subalias("15", m_Q[1]);
+			register_subalias("16", m_Q[0]);
+		}
+	};
+
+	NETLIB_OBJECT_DERIVED(7477_dip, 7477)
+	{
+		NETLIB_CONSTRUCTOR_DERIVED(7477_dip, 7477)
+		{
+			register_subalias("1", m_D[0]);
+			register_subalias("2", m_D[1]);
+			register_subalias("3", m_C3C4);
+			//register_subalias("4", ); ==> VCC
+			register_subalias("5", m_D[2]);
+			register_subalias("6", m_D[3]);
+			//register_subalias("7", ); ==> NC
+
+			register_subalias("8",  m_Q[3]);
+			register_subalias("9",  m_Q[2]);
+			//register_subalias("10", ); ==> NC
+			//register_subalias("11", ); ==> GND
+			register_subalias("12", m_C1C2);
+			register_subalias("13", m_Q[1]);
+			register_subalias("14", m_Q[0]);
+		}
+	};
+
+	NETLIB_UPDATE(7475)
+	{
+		unsigned start_q = m_last_Q;
+
+		NETLIB_PARENT_UPDATE(7477);
+
+		for (std::size_t i=0; i<4; i++)
+		{
+			unsigned last_bit = (m_last_Q >> i) & 1;
+			unsigned start_bit = (start_q >> i) & 1;
+			if (last_bit != start_bit)
+				m_QQ[i].push(last_bit ^ 1, last_bit != 0 ? NLTIME_FROM_NS(15) : NLTIME_FROM_NS(40));
+		}
+	}
+
+	void NETLIB_NAME(7477)::update_outputs(std::size_t start, std::size_t end)
+	{
+		for (std::size_t i=start; i<end; i++)
+		{
+			netlist_sig_t d = m_D[i]();
+			if (d != ((m_last_Q >> i) & 1))
+				m_Q[i].push(d, d != 0 ? NLTIME_FROM_NS(30) : NLTIME_FROM_NS(25));
+			m_last_Q &= ~(1 << i);
+			m_last_Q |= d << i;
+		}
+	}
+
+	NETLIB_RESET(7477)
+	{
+		m_last_Q = 0;
+	}
+
+	NETLIB_UPDATE(7477)
+	{
+		netlist_sig_t c1c2 = m_C1C2();
+		netlist_sig_t c3c4 = m_C3C4();
+		if (c1c2 && c3c4)
+		{
+			update_outputs(0, 4);
+		}
+		else if (c1c2)
+		{
+			update_outputs(0, 2);
+		}
+		else if (c3c4)
+		{
+			update_outputs(2, 4);
+		}
+
+	}
+
+	NETLIB_DEVICE_IMPL(7475)
+	NETLIB_DEVICE_IMPL(7475_dip)
+	NETLIB_DEVICE_IMPL(7477)
+	NETLIB_DEVICE_IMPL(7477_dip)
+
+	} //namespace devices
+} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_7475.h b/src/lib/netlist/devices/nld_7475.h
new file mode 100644
index 0000000..5689d6a
--- /dev/null
+++ b/src/lib/netlist/devices/nld_7475.h
@@ -0,0 +1,62 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ * nld_7475.h
+ *
+ *  7475: 4-Bit Bistable Latches with Complementary Outputs
+ *  7477: 4-Bit Bistable Latches
+ *
+ *          +----------+               +----------+
+ *      1QQ |1   ++  16| 1Q         1D |1   ++  14| 1Q
+ *       1D |2       15| 2Q         2D |2       13| 2Q
+ *       2D |3       14| 2QQ      3C4C |3       12| 1C2C
+ *     3C4C |4  7475 13| 1C2C      VCC |4  7477 11| GND
+ *      VCC |5       12| GND        3D |5       10| NC
+ *       3D |6       11| 3QQ        4D |6        9| 3Q
+ *       4D |7       10| 3Q         NC |7        8| 4Q
+ *      4QQ |8        9| 4Q            +----------+
+ *          +----------+
+ *
+ *
+ *          Function table
+ *
+ *          +---+---++---+-----+
+ *          | D | C || Q | QQ  |
+ *          +===+===++===+=====+
+ *          | 0 | 1 || 0 |  1  |
+ *          | 1 | 1 || 1 |  0  |
+ *          | X | 0 || Q0| Q0Q |
+ *          +---+---++---+-----+
+ *
+ *  Naming conventions follow Texas instruments datasheet
+ *
+ */
+
+#ifndef NLD_7475_H_
+#define NLD_7475_H_
+
+#include "nl_setup.h"
+
+#define PARAMS_7475_7477(name, cC1C2, cC3C4, cD1, cD2, cD3, cD4)    \
+		NET_CONNECT(name, C1C2, cC1C2)      \
+		NET_CONNECT(name, C3C4, cC3C4)      \
+		NET_CONNECT(name, D1,   cD1)        \
+		NET_CONNECT(name, D2,   cD2)        \
+		NET_CONNECT(name, D3,   cD3)        \
+		NET_CONNECT(name, D4,   cD4)
+
+#define TTL_7475(name, cC1C2, cC3C4, cD1, cD2, cD3, cD4)    \
+		NET_REGISTER_DEV(TTL_7475, name)    \
+		PARAMS_7475_7477(name, cC1C2, cC3C4, cD1, cD2, cD3, cD4)
+
+#define TTL_7477(name, cC1C2, cC3C4, cD1, cD2, cD3, cD4)    \
+		NET_REGISTER_DEV(TTL_7477, name)    \
+		PARAMS_7475_7477(name, cC1C2, cC3C4, cD1, cD2, cD3, cD4)
+
+#define TTL_7475_DIP(name)                      \
+		NET_REGISTER_DEV(TTL_7475_DIP, name)
+
+#define TTL_7477_DIP(name)                      \
+		NET_REGISTER_DEV(TTL_7477_DIP, name)
+
+#endif /* NLD_7475_H_ */
diff --git a/src/lib/netlist/devices/nld_7485.cpp b/src/lib/netlist/devices/nld_7485.cpp
new file mode 100644
index 0000000..631257e
--- /dev/null
+++ b/src/lib/netlist/devices/nld_7485.cpp
@@ -0,0 +1,107 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ * nld_7485.cpp
+ *
+ */
+
+#include "nld_7485.h"
+
+namespace netlist
+{
+	namespace devices
+	{
+	NETLIB_OBJECT(7485)
+	{
+		NETLIB_CONSTRUCTOR(7485)
+		, m_A(*this, {{"A0", "A1", "A2", "A3"}})
+		, m_B(*this, {{"B0", "B1", "B2", "B3"}})
+		, m_LTIN(*this, "LTIN")
+		, m_EQIN(*this, "EQIN")
+		, m_GTIN(*this, "GTIN")
+		, m_LTOUT(*this, "LTOUT")
+		, m_EQOUT(*this, "EQOUT")
+		, m_GTOUT(*this, "GTOUT")
+		{
+		}
+
+		NETLIB_UPDATEI();
+
+		void update_outputs(unsigned gt, unsigned lt, unsigned eq);
+
+	protected:
+		object_array_t<logic_input_t, 4> m_A;
+		object_array_t<logic_input_t, 4> m_B;
+		logic_input_t m_LTIN;
+		logic_input_t m_EQIN;
+		logic_input_t m_GTIN;
+		logic_output_t m_LTOUT;
+		logic_output_t m_EQOUT;
+		logic_output_t m_GTOUT;
+	};
+
+	NETLIB_OBJECT_DERIVED(7485_dip, 7485)
+	{
+		NETLIB_CONSTRUCTOR_DERIVED(7485_dip, 7485)
+		{
+			register_subalias("1", m_B[3]);
+			register_subalias("2", m_LTIN);
+			register_subalias("3", m_EQIN);
+			register_subalias("4", m_GTIN);
+			register_subalias("5", m_GTOUT);
+			register_subalias("6", m_EQOUT);
+			register_subalias("7", m_LTOUT);
+
+			register_subalias("9",  m_B[0]);
+			register_subalias("10", m_A[0]);
+			register_subalias("11", m_B[1]);
+			register_subalias("12", m_A[1]);
+			register_subalias("13", m_A[2]);
+			register_subalias("14", m_B[2]);
+			register_subalias("15", m_A[3]);
+
+		}
+	};
+
+	void NETLIB_NAME(7485)::update_outputs(unsigned gt, unsigned lt, unsigned eq)
+	{
+		m_GTOUT.push(gt, NLTIME_FROM_NS(23));
+		m_LTOUT.push(lt, NLTIME_FROM_NS(23));
+		m_EQOUT.push(eq, NLTIME_FROM_NS(23));
+	}
+
+	// FIXME: Timing
+	NETLIB_UPDATE(7485)
+	{
+		for (std::int_fast32_t i = 3; i >= 0; i++)
+		{
+			if (m_A[i]() > m_B[i]())
+			{
+				update_outputs(1, 0, 0);
+				return;
+			}
+			else if (m_A[i]() < m_B[i]())
+			{
+				update_outputs(0, 1, 0);
+				return;
+			}
+		}
+
+		// must be == if we got here
+		if (m_EQIN())
+			update_outputs(0, 0, 1);
+		else if (m_GTIN() && m_LTIN())
+			update_outputs(0, 0, 0);
+		else if (m_GTIN())
+			update_outputs(1, 0, 0);
+		else if (m_LTIN())
+			update_outputs(0, 1, 0);
+		else
+			update_outputs(1, 1, 0);
+	}
+
+	NETLIB_DEVICE_IMPL(7485)
+	NETLIB_DEVICE_IMPL(7485_dip)
+
+	} //namespace devices
+} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_7485.h b/src/lib/netlist/devices/nld_7485.h
new file mode 100644
index 0000000..77ff6b0
--- /dev/null
+++ b/src/lib/netlist/devices/nld_7485.h
@@ -0,0 +1,45 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ * nld_7485.h
+ *
+ *  DM7485: 4-bit Magnitude Comparators
+ *
+ *          +------------+
+ *       B3 |1    ++   16| VCC
+ *     LTIN |2         15| A3
+ *     EQIN |3         14| B2
+ *     GTIN |4   7485  13| A2
+ *    GTOUT |5         12| A1
+ *    EQOUT |6         11| B1
+ *    LTOUT |7         10| A0
+ *      GND |8          9| B0
+ *          +------------+
+ *
+ *  Naming convention attempts to follow Texas Instruments datasheet
+ *
+ */
+
+#ifndef NLD_7485_H_
+#define NLD_7485_H_
+
+#include "nl_setup.h"
+
+#define TTL_7485(name, cA0, cA1, cA2, cA3, cB0, cB1, cB2, cB3, cLTIN, cEQIN, cGTIN)    \
+		NET_REGISTER_DEV(TTL_7485, name)    \
+		NET_CONNECT(name, A0,   cA0)    \
+		NET_CONNECT(name, A1,   cA1)    \
+		NET_CONNECT(name, A2,   cA2)    \
+		NET_CONNECT(name, A3,   cA3)    \
+		NET_CONNECT(name, B0,   cB0)    \
+		NET_CONNECT(name, B1,   cB1)    \
+		NET_CONNECT(name, B2,   cB2)    \
+		NET_CONNECT(name, B3,   cB3)    \
+		NET_CONNECT(name, LTIN, cLTIN)  \
+		NET_CONNECT(name, EQIN, cEQIN)  \
+		NET_CONNECT(name, GTIN, cGTIN)
+
+#define TTL_7485_DIP(name)                                                     \
+		NET_REGISTER_DEV(TTL_7485_DIP, name)
+
+#endif /* NLD_7485_H_ */
diff --git a/src/lib/netlist/devices/nld_82S115.cpp b/src/lib/netlist/devices/nld_82S115.cpp
new file mode 100644
index 0000000..873acef
--- /dev/null
+++ b/src/lib/netlist/devices/nld_82S115.cpp
@@ -0,0 +1,113 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ * nld_82S115.cpp
+ *
+ */
+
+#include "nld_82S115.h"
+
+namespace netlist
+{
+	namespace devices
+	{
+	NETLIB_OBJECT(82S115)
+	{
+		NETLIB_CONSTRUCTOR(82S115)
+		, m_A(*this, {{"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8"}})
+		, m_CE1(*this, "CE1")
+		, m_CE2Q(*this, "CE2Q")
+		, m_STROBE(*this, "STROBE")
+		, m_O(*this, {{"O1", "O2", "O3", "O4", "O5", "O6", "O7", "O8"}})
+		, m_last_O(*this, "m_last_O", 0)
+		, m_ROM(*this, "m_ROM", nullptr)
+		{
+		}
+
+		NETLIB_RESETI();
+		NETLIB_UPDATEI();
+
+	protected:
+		object_array_t<logic_input_t, 9> m_A;
+		logic_input_t m_CE1;
+		logic_input_t m_CE2Q;
+		logic_input_t m_STROBE;
+		object_array_t<logic_output_t, 8> m_O;
+
+		state_var<unsigned> m_last_O;
+
+		param_ptr_t m_ROM; // 4096 bits, 512x8
+	};
+
+	NETLIB_OBJECT_DERIVED(82S115_dip, 82S115)
+	{
+		NETLIB_CONSTRUCTOR_DERIVED(82S115_dip, 82S115)
+		{
+			register_subalias("21",    m_A[0]);
+			register_subalias("22",    m_A[1]);
+			register_subalias("23",    m_A[2]);
+			register_subalias("1",     m_A[3]);
+			register_subalias("2",     m_A[4]);
+			register_subalias("3",     m_A[5]);
+			register_subalias("4",     m_A[6]);
+			register_subalias("5",     m_A[7]);
+			register_subalias("6",     m_A[8]);
+
+			register_subalias("20",    m_CE1);
+			register_subalias("19",    m_CE2Q);
+
+			// register_subalias("13",    m_FE1);
+			// register_subalias("11",    m_FE2);
+
+			register_subalias("18",    m_STROBE);
+
+			register_subalias("7",     m_O[0]);
+			register_subalias("8",     m_O[1]);
+			register_subalias("9",     m_O[2]);
+			register_subalias("10",    m_O[3]);
+			register_subalias("14",    m_O[4]);
+			register_subalias("15",    m_O[5]);
+			register_subalias("16",    m_O[6]);
+			register_subalias("17",    m_O[7]);
+		}
+	};
+
+	NETLIB_RESET(82S115)
+	{
+		m_last_O = 0;
+	}
+
+	// FIXME: timing!
+	NETLIB_UPDATE(82S115)
+	{
+		unsigned o = 0;
+
+		if (m_CE1() && !m_CE2Q())
+		{
+			if (m_STROBE())
+			{
+				unsigned a = 0;
+				for (std::size_t i=0; i<9; i++)
+					a |= (m_A[i]() << i);
+
+				if (m_ROM() != nullptr)
+					o = ((std::uint_fast8_t*)(m_ROM()))[a];
+			}
+			else
+			{
+				o = m_last_O;
+			}
+		}
+
+		m_last_O = o;
+
+		// FIXME: Outputs are tristate. This needs to be properly implemented
+		for (std::size_t i=0; i<8; i++)
+			m_O[i].push((o >> i) & 1, NLTIME_FROM_NS(40)); // FIXME: Timing
+	}
+
+	NETLIB_DEVICE_IMPL(82S115)
+	NETLIB_DEVICE_IMPL(82S115_dip)
+
+	} //namespace devices
+} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_82S115.h b/src/lib/netlist/devices/nld_82S115.h
new file mode 100644
index 0000000..e8b538d
--- /dev/null
+++ b/src/lib/netlist/devices/nld_82S115.h
@@ -0,0 +1,51 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ * nld_82S115.h
+ *
+ *  82S115: 4K-bit TTL bipolar PROM (512 x 8)
+ *
+ *          +--------------+
+ *       A3 |1     ++    24| VCC
+ *       A4 |2           23| A2
+ *       A5 |3           22| A1
+ *       A6 |4   82S115  21| A0
+ *       A7 |5           20| CE1Q
+ *       A8 |6           19| CE2
+ *       O1 |7           18| STROBE
+ *       O2 |8           17| O8
+ *       O3 |9           16| O7
+ *       O4 |10          15| O6
+ *      FE2 |11          14| O5
+ *      GND |12          13| FE1
+ *          +--------------+
+ *
+ *
+ *  Naming conventions follow Signetics datasheet
+ *
+ */
+
+#ifndef NLD_82S115_H_
+#define NLD_82S115_H_
+
+#include "nl_setup.h"
+
+#define PROM_82S115(name, cCE1, cCE2Q, cA0, cA1, cA2, cA3, cA4, cA5, cA6, cA7, cA8, cSTROBE)    \
+		NET_REGISTER_DEV(PROM_82S115, name) \
+		NET_CONNECT(name, CE1Q,   cCE1Q)    \
+		NET_CONNECT(name, CE2Q,   cCE2Q)    \
+		NET_CONNECT(name, A0,     cA0)      \
+		NET_CONNECT(name, A1,     cA1)      \
+		NET_CONNECT(name, A2,     cA2)      \
+		NET_CONNECT(name, A3,     cA3)      \
+		NET_CONNECT(name, A4,     cA4)      \
+		NET_CONNECT(name, A5,     cA5)      \
+		NET_CONNECT(name, A6,     cA6)      \
+		NET_CONNECT(name, A7,     cA7)      \
+		NET_CONNECT(name, A8,     cA8)      \
+		NET_CONNECT(name, STROBE, cSTROBE)
+
+#define PROM_82S115_DIP(name)                                 \
+		NET_REGISTER_DEV(PROM_82S115_DIP, name)
+
+#endif /* NLD_82S115_H_ */
diff --git a/src/lib/netlist/devices/nld_82S123.cpp b/src/lib/netlist/devices/nld_82S123.cpp
new file mode 100644
index 0000000..ab0a58b
--- /dev/null
+++ b/src/lib/netlist/devices/nld_82S123.cpp
@@ -0,0 +1,84 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ * nld_82S123.cpp
+ *
+ */
+
+#include "nld_82S123.h"
+
+namespace netlist
+{
+	namespace devices
+	{
+	NETLIB_OBJECT(82S123)
+	{
+		NETLIB_CONSTRUCTOR(82S123)
+		, m_A(*this, {{"A0", "A1", "A2", "A3", "A4"}})
+		, m_CEQ(*this, "CEQ")
+		, m_O(*this, {{"O1", "O2", "O3", "O4", "O5", "O6", "O7", "O8"}})
+		, m_ROM(*this, "m_ROM", nullptr)
+		{
+		}
+
+		NETLIB_UPDATEI();
+
+	protected:
+		object_array_t<logic_input_t, 5> m_A;
+		logic_input_t m_CEQ;
+		object_array_t<logic_output_t, 8> m_O;
+
+		param_ptr_t m_ROM; // 256 bits, 32x8
+	};
+
+	NETLIB_OBJECT_DERIVED(82S123_dip, 82S123)
+	{
+		NETLIB_CONSTRUCTOR_DERIVED(82S123_dip, 82S123)
+		{
+			register_subalias("1",     m_O[0]);
+			register_subalias("2",     m_O[1]);
+			register_subalias("3",     m_O[2]);
+			register_subalias("4",     m_O[3]);
+			register_subalias("5",     m_O[4]);
+			register_subalias("6",     m_O[5]);
+			register_subalias("7",     m_O[6]);
+			register_subalias("8",     m_O[7]);
+
+			register_subalias("15",    m_CEQ);
+
+			register_subalias("10",    m_A[0]);
+			register_subalias("11",    m_A[1]);
+			register_subalias("12",    m_A[2]);
+			register_subalias("13",    m_A[3]);
+			register_subalias("14",    m_A[4]);
+		}
+	};
+
+	// FIXME: timing!
+	NETLIB_UPDATE(82S123)
+	{
+		unsigned o = 0xff;
+
+		netlist_time delay = NLTIME_FROM_NS(35);
+		if (!m_CEQ())
+		{
+			unsigned a = 0;
+			for (std::size_t i=0; i<5; i++)
+				a |= (m_A[i]() << i);
+
+			if (m_ROM() != nullptr)
+				o = ((std::uint_fast8_t*)(m_ROM()))[a];
+
+			delay = NLTIME_FROM_NS(50);
+		}
+
+		// FIXME: Outputs are tristate. This needs to be properly implemented
+		for (std::size_t i=0; i<8; i++)
+			m_O[i].push((o >> i) & 1, delay);
+	}
+
+	NETLIB_DEVICE_IMPL(82S123)
+	NETLIB_DEVICE_IMPL(82S123_dip)
+
+	} //namespace devices
+} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_82S123.h b/src/lib/netlist/devices/nld_82S123.h
new file mode 100644
index 0000000..a04e169
--- /dev/null
+++ b/src/lib/netlist/devices/nld_82S123.h
@@ -0,0 +1,42 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ * nld_82S123.h
+ *
+ *  82S23: 256-bit (32x8) TTL bipolar PROM with open-collector outputs
+ *  82S123: 256-bit (32x8) TTL bipolar PROM with tri-state outputs
+ *
+ *          +--------------+
+ *       O1 |1     ++    16| VCC
+ *       O2 |2           15| CEQ
+ *       O3 |3           14| A4
+ *       O4 |4   82S123  13| A3
+ *       O5 |5           12| A2
+ *       O6 |6           11| A1
+ *       O7 |7           10| A0
+ *      GND |8            9| O8
+ *          +--------------+
+ *
+ *
+ *  Naming conventions follow Philips datasheet
+ *
+ */
+
+#ifndef NLD_82S123_H_
+#define NLD_82S123_H_
+
+#include "nl_setup.h"
+
+#define PROM_82S123(name, cCEQ, cA0, cA1, cA2, cA3, cA4)    \
+		NET_REGISTER_DEV(PROM_82S123, name) \
+		NET_CONNECT(name, CEQ, cCEQ)    \
+		NET_CONNECT(name, A0,  cA0) \
+		NET_CONNECT(name, A1,  cA1) \
+		NET_CONNECT(name, A2,  cA2) \
+		NET_CONNECT(name, A3,  cA3) \
+		NET_CONNECT(name, A4,  cA4)
+
+#define PROM_82S123_DIP(name)                                 \
+		NET_REGISTER_DEV(PROM_82S123_DIP, name)
+
+#endif /* NLD_82S123_H_ */
diff --git a/src/lib/netlist/devices/nld_82S126.cpp b/src/lib/netlist/devices/nld_82S126.cpp
new file mode 100644
index 0000000..dd1d6ad
--- /dev/null
+++ b/src/lib/netlist/devices/nld_82S126.cpp
@@ -0,0 +1,86 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ * nld_82S126.cpp
+ *
+ */
+
+#include "nld_82S126.h"
+
+namespace netlist
+{
+	namespace devices
+	{
+	NETLIB_OBJECT(82S126)
+	{
+		NETLIB_CONSTRUCTOR(82S126)
+		, m_A(*this, {{"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7" }})
+		, m_CE1Q(*this, "CE1Q")
+		, m_CE2Q(*this, "CE2Q")
+		, m_O(*this, {{"O1", "O2", "O3", "O4" }})
+		, m_ROM(*this, "m_ROM", nullptr)
+		{
+		}
+
+		NETLIB_UPDATEI();
+
+	protected:
+		object_array_t<logic_input_t, 8> m_A;
+		logic_input_t m_CE1Q;
+		logic_input_t m_CE2Q;
+		object_array_t<logic_output_t, 4> m_O;
+
+		param_ptr_t m_ROM; // 1024 bits, 32x32, used as 256x4
+	};
+
+	NETLIB_OBJECT_DERIVED(82S126_dip, 82S126)
+	{
+		NETLIB_CONSTRUCTOR_DERIVED(82S126_dip, 82S126)
+		{
+			register_subalias("5",     m_A[0]);
+			register_subalias("6",     m_A[1]);
+			register_subalias("7",     m_A[2]);
+			register_subalias("4",     m_A[3]);
+			register_subalias("3",     m_A[4]);
+			register_subalias("2",     m_A[5]);
+			register_subalias("1",     m_A[6]);
+			register_subalias("15",    m_A[7]);
+
+			register_subalias("13",    m_CE1Q);
+			register_subalias("14",    m_CE2Q);
+
+			register_subalias("12",    m_O[0]);
+			register_subalias("11",    m_O[1]);
+			register_subalias("10",    m_O[2]);
+			register_subalias("9",     m_O[3]);
+		}
+	};
+
+	// FIXME: timing!
+	NETLIB_UPDATE(82S126)
+	{
+		unsigned o = 0xf;
+
+		netlist_time delay = NLTIME_FROM_NS(25);
+		if (!m_CE1Q() && !m_CE2Q())
+		{
+			unsigned a = 0;
+			for (std::size_t i=0; i<8; i++)
+			a |= (m_A[i]() << i);
+
+			if (m_ROM() != nullptr)
+				o = ((std::uint_fast8_t*)(m_ROM()))[a];
+
+			delay = NLTIME_FROM_NS(50);
+		}
+
+		// FIXME: Outputs are tristate. This needs to be properly implemented
+		for (std::size_t i=0; i<4; i++)
+			m_O[i].push((o >> i) & 1, delay);
+	}
+
+	NETLIB_DEVICE_IMPL(82S126)
+	NETLIB_DEVICE_IMPL(82S126_dip)
+
+	} //namespace devices
+} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_82S126.h b/src/lib/netlist/devices/nld_82S126.h
new file mode 100644
index 0000000..27dd221
--- /dev/null
+++ b/src/lib/netlist/devices/nld_82S126.h
@@ -0,0 +1,45 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ * nld_82S126.h
+ *
+ *  82S126: 1K-bit TTL bipolar PROM
+ *
+ *          +--------------+
+ *       A6 |1     ++    16| VCC
+ *       A5 |2           15| Q7
+ *       A4 |3           14| CE2Q
+ *       A3 |4   82S126  13| CE1Q
+ *       A0 |5           12| O1
+ *       A1 |6           11| O2
+ *       A2 |7           10| O3
+ *      GND |8            9| O4
+ *          +--------------+
+ *
+ *
+ *  Naming conventions follow Signetics datasheet
+ *
+ */
+
+#ifndef NLD_82S126_H_
+#define NLD_82S126_H_
+
+#include "nl_setup.h"
+
+#define PROM_82S126(name, cCE1Q, cCE2Q, cA0, cA1, cA2, cA3, cA4, cA5, cA6, cA7) \
+		NET_REGISTER_DEV(PROM_82S126, name) \
+		NET_CONNECT(name, CE1Q, cCE1Q)  \
+		NET_CONNECT(name, CE2Q, cCE2Q)  \
+		NET_CONNECT(name, A0,   cA0)    \
+		NET_CONNECT(name, A1,   cA1)    \
+		NET_CONNECT(name, A2,   cA2)    \
+		NET_CONNECT(name, A3,   cA3)    \
+		NET_CONNECT(name, A4,   cA4)    \
+		NET_CONNECT(name, A5,   cA5)    \
+		NET_CONNECT(name, A6,   cA6)    \
+		NET_CONNECT(name, A7,   cA7)
+
+#define PROM_82S126_DIP(name)                                 \
+		NET_REGISTER_DEV(PROM_82S126_DIP, name)
+
+#endif /* NLD_82S126_H_ */
diff --git a/src/lib/netlist/devices/nld_9312.h b/src/lib/netlist/devices/nld_9312.h
index a787b38..5608ba9 100644
--- a/src/lib/netlist/devices/nld_9312.h
+++ b/src/lib/netlist/devices/nld_9312.h
@@ -39,8 +39,20 @@
 
 #include "nl_setup.h"
 
-#define TTL_9312(name)                                                          \
-		NET_REGISTER_DEV(TTL_9312, name)
+#define TTL_9312(name, cA, cB, cC, cD0, cD1, cD2, cD3, cD4, cD5, cD6, cD7, cSTROBE)     \
+		NET_REGISTER_DEV(TTL_9312, name)    \
+		NET_CONNECT(name, A,      cA)       \
+		NET_CONNECT(name, B,      cB)       \
+		NET_CONNECT(name, C,      cC)       \
+		NET_CONNECT(name, D0,     cD0)      \
+		NET_CONNECT(name, D1,     cD1)      \
+		NET_CONNECT(name, D2,     cD2)      \
+		NET_CONNECT(name, D3,     cD3)      \
+		NET_CONNECT(name, D4,     cD4)      \
+		NET_CONNECT(name, D5,     cD5)      \
+		NET_CONNECT(name, D6,     cD6)      \
+		NET_CONNECT(name, D7,     cD7)      \
+		NET_CONNECT(name, STROBE, cSTROBE)
 
 #define TTL_9312_DIP(name)                                                      \
 		NET_REGISTER_DEV(TTL_9312_DIP, name)
diff --git a/src/lib/netlist/devices/nld_9316.h b/src/lib/netlist/devices/nld_9316.h
index ab3fb46..b0be896 100644
--- a/src/lib/netlist/devices/nld_9316.h
+++ b/src/lib/netlist/devices/nld_9316.h
@@ -44,6 +44,8 @@
  *
  *  Naming conventions follow National Semiconductor datasheet
  *
+ *  TODO: DM74161 is compatible to DM9316 (both asynchronous clear)
+ *        DM74163 has asynchronous clear (on L to H transition of clock)
  */
 
 #ifndef NLD_9316_H_
diff --git a/src/lib/netlist/devices/nld_9322.cpp b/src/lib/netlist/devices/nld_9322.cpp
new file mode 100644
index 0000000..881ec9e
--- /dev/null
+++ b/src/lib/netlist/devices/nld_9322.cpp
@@ -0,0 +1,114 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ * nld_9322.cpp
+ *
+ */
+
+#include "nld_9322.h"
+
+namespace netlist
+{
+	namespace devices
+	{
+	NETLIB_OBJECT(9322_selector)
+	{
+		NETLIB_CONSTRUCTOR(9322_selector)
+		, m_A(*this, "A")
+		, m_B(*this, "B")
+		, m_Y(*this, "Y")
+		{
+		}
+
+		void update_outputs(const netlist_sig_t strobe, const netlist_sig_t select);
+
+	public:
+		logic_input_t m_A;
+		logic_input_t m_B;
+		logic_output_t m_Y;
+	};
+
+	// FIXME: Timing
+	void NETLIB_NAME(9322_selector)::update_outputs(const netlist_sig_t strobe, const netlist_sig_t select)
+	{
+		if (strobe)
+			m_Y.push(0, NLTIME_FROM_NS(21));
+		else if (select)
+			m_Y.push(m_B(), NLTIME_FROM_NS(14));
+		else
+			m_Y.push(m_A(), NLTIME_FROM_NS(14));
+	}
+
+	NETLIB_OBJECT(9322)
+	{
+		NETLIB_CONSTRUCTOR(9322)
+		, m_1(*this, "1")
+		, m_2(*this, "2")
+		, m_3(*this, "3")
+		, m_4(*this, "4")
+		, m_SELECT(*this, "SELECT")
+		, m_STROBE(*this, "STROBE")
+		{
+			register_subalias("A1", m_1.m_A);
+			register_subalias("B1", m_1.m_B);
+			register_subalias("Y1", m_1.m_Y);
+			register_subalias("A2", m_2.m_A);
+			register_subalias("B2", m_2.m_B);
+			register_subalias("Y2", m_2.m_Y);
+			register_subalias("A3", m_3.m_A);
+			register_subalias("B3", m_3.m_B);
+			register_subalias("Y3", m_3.m_Y);
+			register_subalias("A4", m_4.m_A);
+			register_subalias("B4", m_4.m_B);
+			register_subalias("Y4", m_4.m_Y);
+		}
+
+		NETLIB_UPDATEI();
+
+	protected:
+		NETLIB_SUB(9322_selector) m_1;
+		NETLIB_SUB(9322_selector) m_2;
+		NETLIB_SUB(9322_selector) m_3;
+		NETLIB_SUB(9322_selector) m_4;
+
+		logic_input_t m_SELECT;
+		logic_input_t m_STROBE;
+	};
+
+	NETLIB_OBJECT_DERIVED(9322_dip, 9322)
+	{
+		NETLIB_CONSTRUCTOR_DERIVED(9322_dip, 9322)
+		{
+			register_subalias("1", m_SELECT);
+			register_subalias("2", m_1.m_A);
+			register_subalias("3", m_1.m_B);
+			register_subalias("4", m_1.m_Y);
+			register_subalias("5", m_2.m_A);
+			register_subalias("6", m_2.m_B);
+			register_subalias("7", m_2.m_Y);
+
+			register_subalias("9",  m_3.m_Y);
+			register_subalias("10", m_3.m_B);
+			register_subalias("11", m_3.m_A);
+			register_subalias("12", m_4.m_Y);
+			register_subalias("13", m_4.m_B);
+			register_subalias("14", m_4.m_A);
+			register_subalias("15", m_STROBE);
+		}
+	};
+
+	NETLIB_UPDATE(9322)
+	{
+		const netlist_sig_t strobe = m_STROBE();
+		const netlist_sig_t select = m_SELECT();
+		m_1.update_outputs(strobe, select);
+		m_2.update_outputs(strobe, select);
+		m_3.update_outputs(strobe, select);
+		m_4.update_outputs(strobe, select);
+	}
+
+	NETLIB_DEVICE_IMPL(9322)
+	NETLIB_DEVICE_IMPL(9322_dip)
+
+	} //namespace devices
+} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_9322.h b/src/lib/netlist/devices/nld_9322.h
new file mode 100644
index 0000000..08ec6ef
--- /dev/null
+++ b/src/lib/netlist/devices/nld_9322.h
@@ -0,0 +1,42 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ * nld_9322.h
+ *
+ *  9322: Quad 2-Line to 1-Line Data Selectors/Multiplexers
+ *
+ *          +------------+
+ *   SELECT |1    ++   16| VCC
+ *       A1 |2         15| STROBE
+ *       B1 |3         14| A4
+ *       Y1 |4   9322  13| B4
+ *       A2 |5         12| Y4
+ *       B2 |6         11| A3
+ *       Y2 |7         10| B3
+ *      GND |8          9| Y3
+ *          +------------+
+ *
+ */
+
+#ifndef NLD_9322_H_
+#define NLD_9322_H_
+
+#include "nl_setup.h"
+
+#define TTL_9322(name, cSELECT, cA1, cB1, cA2, cB2, cA3, cB3, cA4, cB4, cSTROBE)    \
+		NET_REGISTER_DEV(TTL_9322, name)    \
+		NET_CONNECT(name, SELECT, cSELECT)  \
+		NET_CONNECT(name, A1,     cA1)      \
+		NET_CONNECT(name, B1,     cB1)      \
+		NET_CONNECT(name, A2,     cA2)      \
+		NET_CONNECT(name, B2,     cB2)      \
+		NET_CONNECT(name, A3,     cA3)      \
+		NET_CONNECT(name, B3,     cB3)      \
+		NET_CONNECT(name, A4,     cA4)      \
+		NET_CONNECT(name, B4,     cB4)      \
+		NET_CONNECT(name, STROBE, cSTROBE)
+
+#define TTL_9322_DIP(name)                                                     \
+		NET_REGISTER_DEV(TTL_9322_DIP, name)
+
+#endif /* NLD_9322_H_ */
diff --git a/src/lib/netlist/devices/nld_am2847.cpp b/src/lib/netlist/devices/nld_am2847.cpp
new file mode 100644
index 0000000..ec4eafc
--- /dev/null
+++ b/src/lib/netlist/devices/nld_am2847.cpp
@@ -0,0 +1,129 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ * nld_am2847.cpp
+ *
+ */
+
+#include "nld_am2847.h"
+
+namespace netlist
+{
+	namespace devices
+	{
+	NETLIB_OBJECT(Am2847_shifter)
+	{
+		NETLIB_CONSTRUCTOR(Am2847_shifter)
+		, m_RC(*this, "RC")
+		, m_IN(*this, "IN")
+		, m_buffer(*this, "m_buffer", 0)
+		, m_OUT(*this, "OUT")
+		{
+		}
+
+	public:
+		void shift();
+
+		logic_input_t m_RC;
+		logic_input_t m_IN;
+
+		state_var<uint_fast16_t[5]> m_buffer;
+
+		logic_output_t m_OUT;
+	};
+
+	NETLIB_OBJECT(AM2847)
+	{
+		NETLIB_CONSTRUCTOR(AM2847)
+		, m_A(*this, "A")
+		, m_B(*this, "B")
+		, m_C(*this, "C")
+		, m_D(*this, "D")
+		, m_CP(*this, "CP")
+		, m_last_CP(*this, "m_last_CP", 0)
+		{
+			register_subalias("OUTA", m_A.m_OUT);
+			register_subalias("OUTB", m_B.m_OUT);
+			register_subalias("OUTC", m_C.m_OUT);
+			register_subalias("OUTD", m_D.m_OUT);
+			register_subalias("INA", m_A.m_IN);
+			register_subalias("INB", m_B.m_IN);
+			register_subalias("INC", m_C.m_IN);
+			register_subalias("IND", m_D.m_IN);
+			register_subalias("RCA", m_A.m_RC);
+			register_subalias("RCB", m_B.m_RC);
+			register_subalias("RCC", m_C.m_RC);
+			register_subalias("RCD", m_D.m_RC);
+		}
+
+		NETLIB_RESETI();
+		NETLIB_UPDATEI();
+
+	protected:
+		NETLIB_SUB(Am2847_shifter) m_A;
+		NETLIB_SUB(Am2847_shifter) m_B;
+		NETLIB_SUB(Am2847_shifter) m_C;
+		NETLIB_SUB(Am2847_shifter) m_D;
+		logic_input_t m_CP;
+
+		state_var<uint_fast32_t> m_last_CP;
+	};
+
+	NETLIB_OBJECT_DERIVED(AM2847_dip, AM2847)
+	{
+		NETLIB_CONSTRUCTOR_DERIVED(AM2847_dip, AM2847)
+		{
+			register_subalias("1", m_A.m_OUT);
+			register_subalias("2", m_A.m_RC);
+			register_subalias("3", m_A.m_IN);
+			register_subalias("4", m_B.m_OUT);
+			register_subalias("5", m_B.m_RC);
+			register_subalias("6", m_B.m_IN);
+			register_subalias("7", m_C.m_OUT);
+
+			register_subalias("9",  m_C.m_RC);
+			register_subalias("10", m_C.m_IN);
+			register_subalias("11", m_CP);
+			register_subalias("13", m_D.m_OUT);
+			register_subalias("14", m_D.m_RC);
+			register_subalias("15", m_D.m_IN);
+
+		}
+	};
+
+	NETLIB_RESET(AM2847)
+	{
+		m_last_CP = 0;
+	}
+
+	NETLIB_UPDATE(AM2847)
+	{
+		if (m_last_CP && !m_CP())
+		{
+			m_A.shift();
+			m_B.shift();
+			m_C.shift();
+			m_D.shift();
+		}
+		m_last_CP = m_CP();
+	}
+
+	inline NETLIB_FUNC_VOID(Am2847_shifter, shift, (void))
+	{
+		unsigned out = m_buffer[0] & 1;
+		uint_fast32_t in = (m_RC() ? out : m_IN());
+		for (std::size_t i=0; i < 5; i++)
+		{
+			uint_fast16_t shift_in = (i == 4) ? in : m_buffer[i + 1];
+			m_buffer[i] >>= 1;
+			m_buffer[i] |= shift_in << 15;
+		}
+
+		m_OUT.push(out, NLTIME_FROM_NS(200));
+	}
+
+	NETLIB_DEVICE_IMPL(AM2847)
+	NETLIB_DEVICE_IMPL(AM2847_dip)
+
+	} //namespace devices
+} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_am2847.h b/src/lib/netlist/devices/nld_am2847.h
new file mode 100644
index 0000000..a820961
--- /dev/null
+++ b/src/lib/netlist/devices/nld_am2847.h
@@ -0,0 +1,41 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ * nld_am2847.h
+ *
+ *  Am2847: Quad 80-Bit Static Shift Register
+ *
+ *          +--------------+
+ *     OUTA |1     ++    16| VSS
+ *      RCA |2           15| IND
+ *      INA |3           14| RCD
+ *     OUTB |4   Am2847  13| OUTD
+ *      RCB |5           12| VGG
+ *      INB |6           11| CP
+ *     OUTC |7           10| INC
+ *      VDD |8            9| RCC
+ *          +--------------+
+ *
+ */
+
+#ifndef NLD_AM2847_H_
+#define NLD_AM2847_H_
+
+#include "nl_setup.h"
+
+#define TTL_AM2847(name, cCP, cINA, cINB, cINC, cIND, cRCA, cRCB, cRCC, cRCD)   \
+		NET_REGISTER_DEV(TTL_AM2847, name)  \
+		NET_CONNECT(name, CP,  cCP)     \
+		NET_CONNECT(name, INA, cINA)    \
+		NET_CONNECT(name, INB, cINB)    \
+		NET_CONNECT(name, INC, cINC)    \
+		NET_CONNECT(name, IND, cIND)    \
+		NET_CONNECT(name, RCA, cRCA)    \
+		NET_CONNECT(name, RCB, cRCB)    \
+		NET_CONNECT(name, RCC, cRCC)    \
+		NET_CONNECT(name, RCD, cRCD)
+
+#define TTL_AM2847_DIP(name)                                                     \
+		NET_REGISTER_DEV(TTL_AM2847_DIP, name)
+
+#endif /* NLD_AM2847_H_ */
diff --git a/src/lib/netlist/devices/nld_dm9334.cpp b/src/lib/netlist/devices/nld_dm9334.cpp
new file mode 100644
index 0000000..c65a05d
--- /dev/null
+++ b/src/lib/netlist/devices/nld_dm9334.cpp
@@ -0,0 +1,149 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ * nld_dm9334.cpp
+ *
+ */
+
+#include "nld_dm9334.h"
+
+namespace netlist
+{
+	namespace devices
+	{
+	NETLIB_OBJECT(9334)
+	{
+		NETLIB_CONSTRUCTOR(9334)
+		, m_CQ(*this, "CQ")
+		, m_EQ(*this, "EQ")
+		, m_D(*this, "D")
+		, m_A(*this, {{"A0", "A1", "A2"}})
+		, m_Q(*this, {{"Q0", "Q1", "Q2", "Q3", "Q4", "Q5", "Q6", "Q7"}})
+		, m_last_CQ(*this, "m_last_CQ", 0)
+		, m_last_EQ(*this, "m_last_EQ", 0)
+		, m_last_D(*this, "m_last_D", 0)
+		, m_last_A(*this, "m_last_A", 0)
+		, m_last_Q(*this, "m_last_Q", 0)
+		{
+		}
+
+		NETLIB_RESETI();
+		NETLIB_UPDATEI();
+
+	protected:
+		logic_input_t m_CQ;
+		logic_input_t m_EQ;
+		logic_input_t m_D;
+		object_array_t<logic_input_t, 3> m_A;
+		object_array_t<logic_output_t, 8> m_Q;
+
+		state_var<unsigned> m_last_CQ;
+		state_var<unsigned> m_last_EQ;
+		state_var<unsigned> m_last_D;
+		state_var<unsigned> m_last_A;
+		state_var<unsigned> m_last_Q;
+	};
+
+	NETLIB_OBJECT_DERIVED(9334_dip, 9334)
+	{
+		NETLIB_CONSTRUCTOR_DERIVED(9334_dip, 9334)
+		{
+			register_subalias("1", m_A[0]);
+			register_subalias("2", m_A[1]);
+			register_subalias("3", m_A[2]);
+			register_subalias("4", m_Q[0]);
+			register_subalias("5", m_Q[1]);
+			register_subalias("6", m_Q[2]);
+			register_subalias("7", m_Q[3]);
+
+			register_subalias("9",  m_Q[4]);
+			register_subalias("10", m_Q[5]);
+			register_subalias("11", m_Q[6]);
+			register_subalias("12", m_Q[7]);
+			register_subalias("13", m_D);
+			register_subalias("14", m_EQ);
+			register_subalias("15", m_CQ);
+
+		}
+	};
+
+	NETLIB_RESET(9334)
+	{
+		m_last_CQ = 0;
+		m_last_EQ = 0;
+		m_last_D = 0;
+		m_last_A = 0;
+		m_last_Q = 0;
+	}
+
+	NETLIB_UPDATE(9334)
+	{
+		uint_fast8_t a = 0;
+		for (std::size_t i=0; i<3; i++)
+		{
+			a |= (m_A[i]() << i);
+		}
+
+		netlist_time delay = NLTIME_FROM_NS(27); // Clear Low to High Level Output (not documented, making reasonable guess)
+
+		if (a != m_last_A)
+		{
+			delay = NLTIME_FROM_NS(35);
+		}
+		else if (m_D() != m_last_D)
+		{
+			if (m_last_D)
+			{
+				delay = NLTIME_FROM_NS(28);
+			}
+			else
+			{
+				delay = NLTIME_FROM_NS(35);
+			}
+		}
+		else if (m_EQ() != m_last_EQ)
+		{
+			if (m_last_EQ)
+			{
+				delay = NLTIME_FROM_NS(27);
+			}
+			else
+			{
+				delay = NLTIME_FROM_NS(28);
+			}
+		}
+
+		uint_fast8_t q = m_last_Q;
+
+		if (!m_CQ())
+		{
+			if (m_EQ())
+			{
+				q = 0;
+			}
+			else
+			{
+				q = m_D() << a;
+			}
+		}
+		else if(!m_EQ())
+		{
+			q &= ~(1 << a);
+			q |= (m_D() << a);
+		}
+
+		m_last_CQ = m_CQ();
+		m_last_EQ = m_EQ();
+		m_last_D = m_D();
+		m_last_A = a;
+		m_last_Q = q;
+
+		for (std::size_t i=0; i<8; i++)
+			m_Q[i].push((q >> i) & 1, delay);
+	}
+
+	NETLIB_DEVICE_IMPL(9334)
+	NETLIB_DEVICE_IMPL(9334_dip)
+
+	} //namespace devices
+} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_dm9334.h b/src/lib/netlist/devices/nld_dm9334.h
new file mode 100644
index 0000000..813ea22
--- /dev/null
+++ b/src/lib/netlist/devices/nld_dm9334.h
@@ -0,0 +1,82 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ * nld_DM9334.h
+ *
+ *  DM9334: 8-Bit Addressable Latch
+ *
+ *          +--------------+
+ *       A0 |1     ++    16| VCC
+ *       A1 |2           15| /C
+ *       A2 |3           14| /E
+ *       Q0 |4   DM9334  13| D
+ *       Q1 |5           12| Q7
+ *       Q2 |6           11| Q6
+ *       Q3 |7           10| Q5
+ *      GND |8            9| Q4
+ *          +--------------+
+ *
+ *          +---+---++---++---+---+---++---+---+---+---+---+---+---+---+
+ *          | C | E || D || A0| A1| A2|| Q0| Q1| Q2| Q3| Q4| Q5| Q6| Q7|
+ *          +===+===++===++===+===+===++===+===+===+===+===+===+===+===+
+ *          | 1 | 0 || X || X | X | X || 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
+ *          +---+---++---++---+---+---++---+---+---+---+---+---+---+---+
+ *          | 1 | 1 || 0 || 0 | 0 | 0 || 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
+ *          | 1 | 1 || 1 || 0 | 0 | 0 || 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
+ *          | 1 | 1 || 0 || 0 | 0 | 1 || 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
+ *          | 1 | 1 || 1 || 0 | 0 | 1 || 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
+ *          | 1 | 1 || 0 || 0 | 1 | 0 || 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
+ *          | 1 | 1 || 1 || 0 | 1 | 0 || 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
+ *          | 1 | 1 || 0 || 0 | 1 | 1 || 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
+ *          | 1 | 1 || 1 || 0 | 1 | 1 || 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
+ *          | 1 | 1 || 0 || 1 | 0 | 0 || 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
+ *          | 1 | 1 || 1 || 1 | 0 | 0 || 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
+ *          | 1 | 1 || 0 || 1 | 0 | 1 || 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
+ *          | 1 | 1 || 1 || 1 | 0 | 1 || 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
+ *          | 1 | 1 || 0 || 1 | 1 | 0 || 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
+ *          | 1 | 1 || 1 || 1 | 1 | 0 || 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
+ *          | 1 | 1 || 0 || 1 | 1 | 1 || 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
+ *          | 1 | 1 || 1 || 1 | 1 | 1 || 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
+ *          +---+---++---++---+---+---++---+---+---+---+---+---+---+---+
+ *          | 0 | 0 || X || X | X | X || P | P | P | P | P | P | P | P |
+ *          +---+---++---++---+---+---++---+---+---+---+---+---+---+---+
+ *          | 0 | 1 || 0 || 0 | 0 | 0 || 0 | P | P | P | P | P | P | P |
+ *          | 0 | 1 || 1 || 0 | 0 | 0 || 1 | P | P | P | P | P | P | P |
+ *          | 0 | 1 || 0 || 0 | 0 | 1 || P | 0 | P | P | P | P | P | P |
+ *          | 0 | 1 || 1 || 0 | 0 | 1 || P | 1 | P | P | P | P | P | P |
+ *          | 0 | 1 || 0 || 0 | 1 | 0 || P | P | 0 | P | P | P | P | P |
+ *          | 0 | 1 || 1 || 0 | 1 | 0 || P | P | 1 | P | P | P | P | P |
+ *          | 0 | 1 || 0 || 0 | 1 | 1 || P | P | P | 0 | P | P | P | P |
+ *          | 0 | 1 || 1 || 0 | 1 | 1 || P | P | P | 1 | P | P | P | P |
+ *          | 0 | 1 || 0 || 1 | 0 | 0 || P | P | P | P | 0 | P | P | P |
+ *          | 0 | 1 || 1 || 1 | 0 | 0 || P | P | P | P | 1 | P | P | P |
+ *          | 0 | 1 || 0 || 1 | 0 | 1 || P | P | P | P | P | 0 | P | P |
+ *          | 0 | 1 || 1 || 1 | 0 | 1 || P | P | P | P | P | 1 | P | P |
+ *          | 0 | 1 || 0 || 1 | 1 | 0 || P | P | P | P | P | P | 0 | P |
+ *          | 0 | 1 || 1 || 1 | 1 | 0 || P | P | P | P | P | P | 1 | P |
+ *          | 0 | 1 || 0 || 1 | 1 | 1 || P | P | P | P | P | P | P | 0 |
+ *          | 0 | 1 || 1 || 1 | 1 | 1 || P | P | P | P | P | P | P | 1 |
+ *          +---+---++---++---+---+---++---+---+---+---+---+---+---+---+
+ *
+ *  Naming convention attempts to follow Texas Instruments / National Semiconductor datasheet Literature Number SNOS382A
+ *
+ */
+
+#ifndef NLD_DM9334_H_
+#define NLD_DM9334_H_
+
+#include "nl_setup.h"
+
+#define TTL_9334(name, cCQ, cEQ, cD, cA0, cA1, cA2) \
+		NET_REGISTER_DEV(TTL_9334, name)    \
+		NET_CONNECT(name, CQ,  cCQ) \
+		NET_CONNECT(name, EQ,  cEQ) \
+		NET_CONNECT(name, D,  cD)   \
+		NET_CONNECT(name, A0, cA0)  \
+		NET_CONNECT(name, A1, cA1)  \
+		NET_CONNECT(name, A2, cA2)
+
+#define TTL_9334_DIP(name)                                                     \
+		NET_REGISTER_DEV(TTL_9334_DIP, name)
+
+#endif /* NLD_DM9334_H_ */
diff --git a/src/lib/netlist/devices/nld_tristate.cpp b/src/lib/netlist/devices/nld_tristate.cpp
new file mode 100644
index 0000000..db21468
--- /dev/null
+++ b/src/lib/netlist/devices/nld_tristate.cpp
@@ -0,0 +1,76 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ * nld_tristate.cpp
+ *
+ */
+
+#include "nld_tristate.h"
+
+namespace netlist
+{
+	namespace devices
+	{
+	NETLIB_OBJECT(tristate)
+	{
+		NETLIB_CONSTRUCTOR(tristate)
+		, m_CEQ(*this, {{ "CEQ1", "CEQ2" }})
+		, m_D(*this, {{ "D1", "D2" }})
+		, m_Q(*this, "Q")
+		{
+		}
+
+		NETLIB_UPDATEI();
+
+	protected:
+		object_array_t<logic_input_t, 2> m_CEQ;
+		object_array_t<logic_input_t, 2> m_D;
+		logic_output_t m_Q;
+	};
+
+	NETLIB_OBJECT(tristate3)
+	{
+		NETLIB_CONSTRUCTOR(tristate3)
+		, m_CEQ(*this, {{ "CEQ1", "CEQ2", "CEQ3" }} )
+		, m_D(*this, {{ "D1", "D2", "D3" }} )
+		, m_Q(*this, "Q")
+		{
+		}
+
+		NETLIB_UPDATEI();
+
+	protected:
+		object_array_t<logic_input_t, 3> m_CEQ;
+		object_array_t<logic_input_t, 3> m_D;
+		logic_output_t m_Q;
+	};
+
+	NETLIB_UPDATE(tristate)
+	{
+		unsigned q = 0;
+		if (!m_CEQ[0]())
+			q |= m_D[0]();
+		if (!m_CEQ[1]())
+			q |= m_D[1]();
+
+		m_Q.push(q, NLTIME_FROM_NS(1));
+	}
+
+	NETLIB_UPDATE(tristate3)
+	{
+		unsigned q = 0;
+		if (!m_CEQ[0]())
+			q |= m_D[0]();
+		if (!m_CEQ[1]())
+			q |= m_D[1]();
+		if (!m_CEQ[2]())
+			q |= m_D[2]();
+
+		m_Q.push(q, NLTIME_FROM_NS(1));
+	}
+
+	NETLIB_DEVICE_IMPL(tristate)
+	NETLIB_DEVICE_IMPL(tristate3)
+
+	} //namespace devices
+} // namespace netlist
diff --git a/src/lib/netlist/devices/nld_tristate.h b/src/lib/netlist/devices/nld_tristate.h
new file mode 100644
index 0000000..604ae7f
--- /dev/null
+++ b/src/lib/netlist/devices/nld_tristate.h
@@ -0,0 +1,31 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*
+ * nld_tristate.h
+ *
+ *  tristate: Hack to merge two tri-stated outputs together
+ *
+ */
+
+#ifndef NLD_TRISTATE_H_
+#define NLD_TRISTATE_H_
+
+#include "nl_setup.h"
+
+#define TTL_TRISTATE(name, cCEQ1, cD1, cCEQ2, cD2)  \
+		NET_REGISTER_DEV(TTL_TRISTATE, name)    \
+		NET_CONNECT(name, CEQ1, cCEQ1)  \
+		NET_CONNECT(name, D1,  cD1)     \
+		NET_CONNECT(name, CEQ2, cCEQ2)  \
+		NET_CONNECT(name, D2,  cD2)
+
+#define TTL_TRISTATE3(name, cCEQ1, cD1, cCEQ2, cD2, cCEQ3, cD3) \
+		NET_REGISTER_DEV(TTL_TRISTATE3, name)   \
+		NET_CONNECT(name, CEQ1, cCEQ1)  \
+		NET_CONNECT(name, D1,  cD1)     \
+		NET_CONNECT(name, CEQ2, cCEQ2)  \
+		NET_CONNECT(name, D2,  cD2)     \
+		NET_CONNECT(name, CEQ3, cCEQ3)  \
+		NET_CONNECT(name, D3, cD3)
+
+#endif /* NLD_TRISTATE_H_ */
diff --git a/src/lib/netlist/macro/nlm_cd4xxx.cpp b/src/lib/netlist/macro/nlm_cd4xxx.cpp
index 95fff08..d169e27 100644
--- a/src/lib/netlist/macro/nlm_cd4xxx.cpp
+++ b/src/lib/netlist/macro/nlm_cd4xxx.cpp
@@ -6,6 +6,7 @@
 #include "devices/nld_system.h"
 #include "devices/nld_4020.h"
 #include "devices/nld_4066.h"
+#include "devices/nld_4316.h"
 
 /*
  *   CD4001BC: Quad 2-Input NOR Buffered B Series Gate
@@ -31,14 +32,14 @@ static NETLIST_START(CD4001_DIP)
 	DUMMY_INPUT(VSS)
 	DUMMY_INPUT(VDD)
 
-	DIPPINS(   /*       +--------------+      */
-		s1.A,  /*    A1 |1     ++    14| VCC  */ VSS.I,
-		s1.B,  /*    B1 |2           13| A6   */ s4.B,
-		s1.Q,  /*    A2 |3           12| Y6   */ s4.A,
-		s2.Q,  /*    Y2 |4    4001   11| A5   */ s4.Q,
-		s2.A,  /*    A3 |5           10| Y5   */ s3.Q,
-		s2.B,  /*    Y3 |6            9| A4   */ s3.B,
-		VDD.I, /*   GND |7            8| Y4   */ s3.A
+	DIPPINS(    /*       +--------------+      */
+		s1.A,   /*    A1 |1     ++    14| VCC  */ VSS.I,
+		s1.B,   /*    B1 |2           13| A6   */ s4.B,
+		s1.Q,   /*    A2 |3           12| Y6   */ s4.A,
+		s2.Q,   /*    Y2 |4    4001   11| A5   */ s4.Q,
+		s2.A,   /*    A3 |5           10| Y5   */ s3.Q,
+		s2.B,   /*    Y3 |6            9| A4   */ s3.B,
+		VDD.I,  /*   GND |7            8| Y4   */ s3.A
 				/*       +--------------+      */
 	)
 
@@ -115,14 +116,14 @@ static NETLIST_START(CD4066_DIP)
 	PARAM(C.BASER, 270.0)
 	PARAM(D.BASER, 270.0)
 
-	DIPPINS(      /*          +--------------+          */
-		A.R.1,    /*   INOUTA |1     ++    14| VDD      */ A.PS.VDD,
-		A.R.2,    /*   OUTINA |2           13| CONTROLA */ A.CTL,
-		B.R.1,    /*   OUTINB |3           12| CONTROLD */ D.CTL,
-		B.R.2,    /*   INOUTB |4    4066   11| INOUTD   */ D.R.1,
-		B.CTL,    /* CONTROLB |5           10| OUTIND   */ D.R.2,
-		C.CTL,    /* CONTROLC |6            9| OUTINC   */ C.R.1,
-		A.PS.VSS, /*      VSS |7            8| INOUTC   */ C.R.2
+	DIPPINS(        /*          +--------------+          */
+		A.R.1,      /*   INOUTA |1     ++    14| VDD      */ A.PS.VDD,
+		A.R.2,      /*   OUTINA |2           13| CONTROLA */ A.CTL,
+		B.R.1,      /*   OUTINB |3           12| CONTROLD */ D.CTL,
+		B.R.2,      /*   INOUTB |4    4066   11| INOUTD   */ D.R.1,
+		B.CTL,      /* CONTROLB |5           10| OUTIND   */ D.R.2,
+		C.CTL,      /* CONTROLC |6            9| OUTINC   */ C.R.1,
+		A.PS.VSS,   /*      VSS |7            8| INOUTC   */ C.R.2
 					/*          +--------------+          */
 	)
 NETLIST_END()
@@ -141,18 +142,47 @@ static NETLIST_START(CD4016_DIP)
 	PARAM(C.BASER, 1000.0)
 	PARAM(D.BASER, 1000.0)
 
-	DIPPINS(      /*          +--------------+          */
-		A.R.1,    /*   INOUTA |1     ++    14| VDD      */ A.PS.VDD,
-		A.R.2,    /*   OUTINA |2           13| CONTROLA */ A.CTL,
-		B.R.1,    /*   OUTINB |3           12| CONTROLD */ D.CTL,
-		B.R.2,    /*   INOUTB |4    4016   11| INOUTD   */ D.R.1,
-		B.CTL,    /* CONTROLB |5           10| OUTIND   */ D.R.2,
-		C.CTL,    /* CONTROLC |6            9| OUTINC   */ C.R.1,
-		A.PS.VSS, /*      VSS |7            8| INOUTC   */ C.R.2
+	DIPPINS(        /*          +--------------+          */
+		A.R.1,      /*   INOUTA |1     ++    14| VDD      */ A.PS.VDD,
+		A.R.2,      /*   OUTINA |2           13| CONTROLA */ A.CTL,
+		B.R.1,      /*   OUTINB |3           12| CONTROLD */ D.CTL,
+		B.R.2,      /*   INOUTB |4    4016   11| INOUTD   */ D.R.1,
+		B.CTL,      /* CONTROLB |5           10| OUTIND   */ D.R.2,
+		C.CTL,      /* CONTROLC |6            9| OUTINC   */ C.R.1,
+		A.PS.VSS,   /*      VSS |7            8| INOUTC   */ C.R.2
 					/*          +--------------+          */
 	)
 NETLIST_END()
 
+static NETLIST_START(CD4316_DIP)
+	CD4316_GATE(A)
+	CD4316_GATE(B)
+	CD4316_GATE(C)
+	CD4316_GATE(D)
+
+	NET_C(A.E, B.E, C.E, D.E)
+	NET_C(A.PS.VDD, B.PS.VDD, C.PS.VDD, D.PS.VDD)
+	NET_C(A.PS.VSS, B.PS.VSS, C.PS.VSS, D.PS.VSS)
+
+	PARAM(A.BASER, 45.0)
+	PARAM(B.BASER, 45.0)
+	PARAM(C.BASER, 45.0)
+	PARAM(D.BASER, 45.0)
+
+	DIPPINS(        /*          +--------------+          */
+		A.R.2,      /*       1Z |1     ++    16| VCC      */ A.PS.VDD,
+		A.R.1,      /*       1Y |2           15| 1S       */ A.S,
+		B.R.1,      /*       2Y |3           14| 4S       */ D.S,
+		B.R.2,      /*       2Z |4    4316   13| 4Z       */ D.R.2,
+		B.S,        /*       2S |5           12| 4Y       */ D.R.1,
+		C.S,        /*       3S |6           11| 3Y       */ C.R.1,
+		A.E,        /*       /E |7           10| 3Z       */ C.R.2,
+		A.PS.VSS,   /*      GND |8            9| VEE      */ VEE
+					/*          +--------------+          */
+	)
+
+NETLIST_END()
+
 NETLIST_START(CD4XXX_lib)
 
 	TRUTHTABLE_START(CD4001_NOR, 2, 1, "")
@@ -169,5 +199,6 @@ NETLIST_START(CD4XXX_lib)
 	LOCAL_LIB_ENTRY(CD4020_DIP)
 	LOCAL_LIB_ENTRY(CD4016_DIP)
 	LOCAL_LIB_ENTRY(CD4066_DIP)
+	LOCAL_LIB_ENTRY(CD4316_DIP)
 
 NETLIST_END()
diff --git a/src/lib/netlist/macro/nlm_cd4xxx.h b/src/lib/netlist/macro/nlm_cd4xxx.h
index acc47f4..de10ff7 100644
--- a/src/lib/netlist/macro/nlm_cd4xxx.h
+++ b/src/lib/netlist/macro/nlm_cd4xxx.h
@@ -41,6 +41,9 @@
 #define CD4016_DIP(name)                                                      \
 		NET_REGISTER_DEV(CD4016_DIP, name)
 
+#define CD4316_DIP(name)                                                      \
+		NET_REGISTER_DEV(CD4016_DIP, name)
+
 /* ----------------------------------------------------------------------------
  *  External declarations
  * ---------------------------------------------------------------------------*/
diff --git a/src/lib/netlist/macro/nlm_opamp.cpp b/src/lib/netlist/macro/nlm_opamp.cpp
index e7571df..38f47d5 100644
--- a/src/lib/netlist/macro/nlm_opamp.cpp
+++ b/src/lib/netlist/macro/nlm_opamp.cpp
@@ -6,18 +6,18 @@
 #include "devices/nld_system.h"
 
 /*
- *   Generic layout with 4 opamps, VCC on pint 4 and GND on pin 11
+ *   Generic layout with 4 opamps, VCC on pin 4 and GND on pin 11
  */
 
 static NETLIST_START(opamp_layout_4_4_11)
-	DIPPINS(      /*   +--------------+   */
-		A.OUT,    /*   |1     ++    14|   */ D.OUT,
-		A.MINUS,  /*   |2           13|   */ D.MINUS,
-		A.PLUS,   /*   |3           12|   */ D.PLUS,
-		A.VCC,    /*   |4           11|   */ A.GND,
-		B.PLUS,   /*   |5           10|   */ C.PLUS,
-		B.MINUS,  /*   |6            9|   */ C.MINUS,
-		B.OUT,    /*   |7            8|   */ C.OUT
+	DIPPINS(        /*   +--------------+   */
+		A.OUT,      /*   |1     ++    14|   */ D.OUT,
+		A.MINUS,    /*   |2           13|   */ D.MINUS,
+		A.PLUS,     /*   |3           12|   */ D.PLUS,
+		A.VCC,      /*   |4           11|   */ A.GND,
+		B.PLUS,     /*   |5           10|   */ C.PLUS,
+		B.MINUS,    /*   |6            9|   */ C.MINUS,
+		B.OUT,      /*   |7            8|   */ C.OUT
 					/*   +--------------+   */
 	)
 	NET_C(A.GND, B.GND, C.GND, D.GND)
@@ -25,21 +25,82 @@ static NETLIST_START(opamp_layout_4_4_11)
 NETLIST_END()
 
 /*
- *   Generic layout with 2 opamps, VCC on pint 8 and GND on pin 4
+ *   Generic layout with 2 opamps, VCC on pin 8 and GND on pin 4
  */
 
 static NETLIST_START(opamp_layout_2_8_4)
-	DIPPINS(      /*   +--------------+   */
-		A.OUT,    /*   |1     ++     8|   */ A.VCC,
-		A.MINUS,  /*   |2            7|   */ B.OUT,
-		A.PLUS,   /*   |3            6|   */ B.MINUS,
-		A.GND,    /*   |4            5|   */ B.PLUS
+	DIPPINS(        /*   +--------------+   */
+		A.OUT,      /*   |1     ++     8|   */ A.VCC,
+		A.MINUS,    /*   |2            7|   */ B.OUT,
+		A.PLUS,     /*   |3            6|   */ B.MINUS,
+		A.GND,      /*   |4            5|   */ B.PLUS
 					/*   +--------------+   */
 	)
 	NET_C(A.GND, B.GND)
 	NET_C(A.VCC, B.VCC)
 NETLIST_END()
 
+/*
+ *   Generic layout with 1 opamp, VCC+ on pin 7, VCC- on pin 4 and compensation
+ */
+
+static NETLIST_START(opamp_layout_1_7_4)
+	DIPPINS(        /*   +--------------+   */
+		OFFSET.N1,  /*   |1     ++     8|   */ NC,
+		MINUS,      /*   |2            7|   */ VCC.PLUS,
+		PLUS,       /*   |3            6|   */ OUT,
+		VCC.MINUS,  /*   |4            5|   */ OFFSET.N2
+					/*   +--------------+   */
+	)
+	NET_C(A.GND, VCC.MINUS)
+	NET_C(A.VCC, VCC.PLUS)
+	NET_C(A.MINUS, MINUS)
+	NET_C(A.PLUS, PLUS)
+	NET_C(A.OUT, OUT)
+NETLIST_END()
+
+/*
+ *   Generic layout with 1 opamp, VCC+ on pin 8, VCC- on pin 5 and compensation
+ */
+
+static NETLIST_START(opamp_layout_1_8_5)
+	DIPPINS(        /*   +--------------+   */
+		NC.1,       /*   |1           10|   */ NC.3,
+		OFFSET.N1,  /*   |2            9|   */ NC.2,
+		MINUS,      /*   |3            8|   */ VCC.PLUS,
+		PLUS,       /*   |4            7|   */ OUT,
+		VCC.MINUS,  /*   |5            6|   */ OFFSET.N2
+					/*   +--------------+   */
+	)
+	NET_C(A.GND, VCC.MINUS)
+	NET_C(A.VCC, VCC.PLUS)
+	NET_C(A.MINUS, MINUS)
+	NET_C(A.PLUS, PLUS)
+	NET_C(A.OUT, OUT)
+NETLIST_END()
+
+/*
+ *   Generic layout with 1 opamp, VCC+ on pin 11, VCC- on pin 6 and compensation
+ */
+
+static NETLIST_START(opamp_layout_1_11_6)
+	DIPPINS(        /*   +--------------+   */
+		NC.1,       /*   |1     ++    14|   */ NC.7,
+		NC.2,       /*   |2           13|   */ NC.6,
+		OFFSET.N1,  /*   |3           12|   */ NC.5,
+		MINUS,      /*   |4           11|   */ VCC.PLUS,
+		PLUS,       /*   |5           10|   */ OUT,
+		VCC.MINUS,  /*   |6            9|   */ OFFSET.N2,
+		NC.3,       /*   |7            8|   */ NC.4
+					/*   +--------------+   */
+	)
+	NET_C(A.GND, VCC.MINUS)
+	NET_C(A.VCC, VCC.PLUS)
+	NET_C(A.MINUS, MINUS)
+	NET_C(A.PLUS, PLUS)
+	NET_C(A.OUT, OUT)
+NETLIST_END()
+
 static NETLIST_START(MB3614_DIP)
 	OPAMP(A, "MB3614")
 	OPAMP(B, "MB3614")
@@ -60,6 +121,27 @@ static NETLIST_START(LM324_DIP)
 
 NETLIST_END()
 
+static NETLIST_START(UA741_DIP8)
+	OPAMP(A, "UA741")
+
+	INCLUDE(opamp_layout_1_7_4)
+
+NETLIST_END()
+
+static NETLIST_START(UA741_DIP10)
+	OPAMP(A, "UA741")
+
+	INCLUDE(opamp_layout_1_8_5)
+
+NETLIST_END()
+
+static NETLIST_START(UA741_DIP14)
+	OPAMP(A, "UA741")
+
+	INCLUDE(opamp_layout_1_11_6)
+
+NETLIST_END()
+
 static NETLIST_START(LM358_DIP)
 	OPAMP(A, "LM358")
 	OPAMP(B, "LM358")
@@ -71,14 +153,20 @@ NETLIST_END()
 NETLIST_START(OPAMP_lib)
 	LOCAL_LIB_ENTRY(opamp_layout_4_4_11)
 	LOCAL_LIB_ENTRY(opamp_layout_2_8_4)
+	LOCAL_LIB_ENTRY(opamp_layout_1_7_4)
+	LOCAL_LIB_ENTRY(opamp_layout_1_8_5)
+	LOCAL_LIB_ENTRY(opamp_layout_1_11_6)
 
 	NET_MODEL("LM324       OPAMP(TYPE=3 VLH=2.0 VLL=0.2 FPF=5 UGF=500k SLEW=0.3M RI=1000k RO=50 DAB=0.00075)")
 	NET_MODEL("LM358       OPAMP(TYPE=3 VLH=2.0 VLL=0.2 FPF=5 UGF=500k SLEW=0.3M RI=1000k RO=50 DAB=0.001)")
 	NET_MODEL("MB3614      OPAMP(TYPE=3 VLH=1.4 VLL=0.02 FPF=2 UGF=500k SLEW=0.6M RI=1000k RO=50 DAB=0.0002)")
+	NET_MODEL("UA741       OPAMP(TYPE=3 VLH=1.0 VLL=1.0 FPF=5 UGF=1000k SLEW=0.5M RI=2000k RO=75 DAB=0.0017)")
 
 	LOCAL_LIB_ENTRY(MB3614_DIP)
 	LOCAL_LIB_ENTRY(LM324_DIP)
 	LOCAL_LIB_ENTRY(LM358_DIP)
-
+	LOCAL_LIB_ENTRY(UA741_DIP8)
+	LOCAL_LIB_ENTRY(UA741_DIP10)
+	LOCAL_LIB_ENTRY(UA741_DIP14)
 
 NETLIST_END()
diff --git a/src/lib/netlist/macro/nlm_ttl74xx.cpp b/src/lib/netlist/macro/nlm_ttl74xx.cpp
index 646ae44..2120d88 100644
--- a/src/lib/netlist/macro/nlm_ttl74xx.cpp
+++ b/src/lib/netlist/macro/nlm_ttl74xx.cpp
@@ -540,6 +540,44 @@ static NETLIST_START(TTL_7486_DIP)
 	)
 NETLIST_END()
 
+/*
+ *  DM74260: Dual 5-Input NOR Gates
+ *                 _________
+ *             Y = A+B+C+D+E
+ *          +---+---+---+---+---++---+
+ *          | A | B | B | B | B || Y |
+ *          +===+===+===+===+===++===+
+ *          | 0 | 0 | 0 | 0 | 0 || 1 |
+ *          | 0 | 0 | 0 | 0 | 1 || 0 |
+ *          | 0 | 0 | 0 | 1 | 0 || 0 |
+ *          | 0 | 0 | 1 | 0 | 0 || 0 |
+ *          | 0 | 1 | 0 | 0 | 0 || 0 |
+ *          | 1 | 0 | 0 | 0 | 0 || 0 |
+ *          +---+---+---+---+---++---+
+ *
+ *  Naming conventions follow Texas Instruments datasheet
+ *
+ */
+
+static NETLIST_START(TTL_74260_DIP)
+	TTL_74260_GATE(s1)
+	TTL_74260_GATE(s2)
+
+	DUMMY_INPUT(GND)
+	DUMMY_INPUT(VCC)
+
+	DIPPINS(   /*       +--------------+      */
+		s1.C,  /*    C1 |1     ++    14| VCC  */ VCC.I,
+		s1.D,  /*    D1 |2           13| B1   */ s1.B,
+		s1.E,  /*    E1 |3           12| A1   */ s1.A,
+		s2.E,  /*    E2 |4   74260   11| D2   */ s2.D,
+		s1.Q,  /*    Y1 |5           10| C2   */ s2.C,
+		s2.Q,  /*    Y2 |6            9| B2   */ s2.B,
+		GND.I, /*   GND |7            8| A2   */ s2.A
+				/*       +--------------+      */
+	)
+NETLIST_END()
+
 NETLIST_START(TTL74XX_lib)
 
 	TRUTHTABLE_START(TTL_7400_GATE, 2, 1, "")
@@ -788,6 +826,28 @@ NETLIST_START(TTL74XX_lib)
 		TT_FAMILY("74XX")
 	TRUTHTABLE_END()
 
+	TRUTHTABLE_START(TTL_74260_GATE, 5, 1, "")
+		TT_HEAD("A,B,C,D,E|Q ")
+		TT_LINE("0,0,0,0,0|1|10")
+		TT_LINE("X,X,X,X,1|0|12")
+		TT_LINE("X,X,X,1,X|0|12")
+		TT_LINE("X,X,1,X,X|0|12")
+		TT_LINE("X,1,X,X,X|0|12")
+		TT_LINE("1,X,X,X,X|0|12")
+		TT_FAMILY("74XX")
+	TRUTHTABLE_END()
+
+	TRUTHTABLE_START(TTL_74260_NOR, 5, 1, "A,B,C,D,E")
+		TT_HEAD("A,B,C,D,E|Q ")
+		TT_LINE("0,0,0,0,0|1|10")
+		TT_LINE("X,X,X,X,1|0|12")
+		TT_LINE("X,X,X,1,X|0|12")
+		TT_LINE("X,X,1,X,X|0|12")
+		TT_LINE("X,1,X,X,X|0|12")
+		TT_LINE("1,X,X,X,X|0|12")
+		TT_FAMILY("74XX")
+	TRUTHTABLE_END()
+
 	LOCAL_LIB_ENTRY(TTL_7400_DIP)
 	LOCAL_LIB_ENTRY(TTL_7402_DIP)
 	LOCAL_LIB_ENTRY(TTL_7404_DIP)
@@ -802,4 +862,5 @@ NETLIST_START(TTL74XX_lib)
 	LOCAL_LIB_ENTRY(TTL_7432_DIP)
 	LOCAL_LIB_ENTRY(TTL_7437_DIP)
 	LOCAL_LIB_ENTRY(TTL_7486_DIP)
+	LOCAL_LIB_ENTRY(TTL_74260_DIP)
 NETLIST_END()
diff --git a/src/lib/netlist/macro/nlm_ttl74xx.h b/src/lib/netlist/macro/nlm_ttl74xx.h
index 54b9dfa..44b3db6 100644
--- a/src/lib/netlist/macro/nlm_ttl74xx.h
+++ b/src/lib/netlist/macro/nlm_ttl74xx.h
@@ -185,6 +185,21 @@
 #define TTL_7486_DIP(name)                                                    \
 		NET_REGISTER_DEV(TTL_7486_DIP, name)
 
+
+#define TTL_74260_GATE(name)                                                   \
+		NET_REGISTER_DEV(TTL_74260_GATE, name)
+
+#define TTL_74260_NOR(name, cA, cB, cC, cD, cE) \
+		NET_REGISTER_DEV(TTL_74260_NOR, name)   \
+		NET_CONNECT(name, A, cA)    \
+		NET_CONNECT(name, B, cB)    \
+		NET_CONNECT(name, C, cC)    \
+		NET_CONNECT(name, D, cD)    \
+		NET_CONNECT(name, E, cE)
+
+#define TTL_74260_DIP(name) \
+		NET_REGISTER_DEV(TTL_74260_DIP, name)
+
 /* ----------------------------------------------------------------------------
  *  External declarations
  * ---------------------------------------------------------------------------*/
diff --git a/src/lib/netlist/nl_base.cpp b/src/lib/netlist/nl_base.cpp
index d8a0161..165ba1c 100644
--- a/src/lib/netlist/nl_base.cpp
+++ b/src/lib/netlist/nl_base.cpp
@@ -482,6 +482,7 @@ param_template_t<C, T>::param_template_t(device_t &device, const pstring name, c
 template class param_template_t<double, param_t::DOUBLE>;
 template class param_template_t<int, param_t::INTEGER>;
 template class param_template_t<bool, param_t::LOGIC>;
+template class param_template_t<std::uint_fast8_t*, param_t::POINTER>;
 template class param_template_t<pstring, param_t::STRING>;
 template class param_template_t<pstring, param_t::MODEL>;
 
diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h
index 55b1ef0..fe799af 100644
--- a/src/lib/netlist/nl_base.h
+++ b/src/lib/netlist/nl_base.h
@@ -125,6 +125,7 @@ class NETLIB_NAME(name) : public device_t
 #define NETLIB_SUBXX(chip) std::unique_ptr< nld_ ## chip >
 
 #define NETLIB_UPDATE(chip) void NETLIB_NAME(chip) :: update(void) NL_NOEXCEPT
+#define NETLIB_PARENT_UPDATE(chip) NETLIB_NAME(chip) :: update();
 
 #define NETLIB_RESET(chip) void NETLIB_NAME(chip) :: reset(void)
 
@@ -832,7 +833,8 @@ namespace netlist
 			STRING,
 			DOUBLE,
 			INTEGER,
-			LOGIC
+			LOGIC,
+			POINTER // Special-case which is always initialized at MAME startup time
 		};
 
 		param_t(const param_type_t atype, device_t &device, const pstring &name);
@@ -868,6 +870,7 @@ namespace netlist
 	using param_str_t = param_template_t<pstring, param_t::STRING>;
 
 	using param_logic_t = param_template_t<bool, param_t::LOGIC>;
+	using param_ptr_t = param_template_t<std::uint_fast8_t*, param_t::POINTER>;
 
 	class param_model_t : public param_str_t
 	{
diff --git a/src/lib/netlist/nl_setup.cpp b/src/lib/netlist/nl_setup.cpp
index 274daba..b55f662 100644
--- a/src/lib/netlist/nl_setup.cpp
+++ b/src/lib/netlist/nl_setup.cpp
@@ -217,6 +217,9 @@ void setup_t::register_and_set_param(pstring name, param_t &param)
 				static_cast<param_int_t &>(param).initial(static_cast<int>(vald));
 			}
 			break;
+			case param_t::POINTER:
+				static_cast<param_ptr_t &>(param).initial(nullptr);
+			break;
 			case param_t::STRING:
 			case param_t::MODEL:
 			{
diff --git a/src/lib/netlist/prg/nltool.cpp b/src/lib/netlist/prg/nltool.cpp
index b095a08..8241daa 100644
--- a/src/lib/netlist/prg/nltool.cpp
+++ b/src/lib/netlist/prg/nltool.cpp
@@ -201,6 +201,9 @@ struct input_t
 			case netlist::param_t::LOGIC:
 				static_cast<netlist::param_logic_t*>(m_param)->setTo(static_cast<bool>(m_value));
 				break;
+			case netlist::param_t::POINTER:
+				static_cast<netlist::param_ptr_t*>(m_param)->setTo(nullptr);
+				break;
 		}
 	}
 
diff --git a/src/lib/util/bitmap.cpp b/src/lib/util/bitmap.cpp
index 82f28e7..c8ceb5d 100644
--- a/src/lib/util/bitmap.cpp
+++ b/src/lib/util/bitmap.cpp
@@ -37,7 +37,7 @@ inline int32_t bitmap_t::compute_rowpixels(int width, int xslop)
 
 inline void bitmap_t::compute_base(int xslop, int yslop)
 {
-	m_base = m_alloc + (m_rowpixels * yslop + xslop) * (m_bpp / 8);
+	m_base = m_alloc.get() + (m_rowpixels * yslop + xslop) * (m_bpp / 8);
 }
 
 
@@ -46,8 +46,24 @@ inline void bitmap_t::compute_base(int xslop, int yslop)
 //  BITMAP ALLOCATION/CONFIGURATION
 //**************************************************************************
 
+bitmap_t::bitmap_t(bitmap_t &&that)
+	: m_alloc(std::move(that.m_alloc))
+	, m_allocbytes(that.m_allocbytes)
+	, m_base(that.m_base)
+	, m_rowpixels(that.m_rowpixels)
+	, m_width(that.m_width)
+	, m_height(that.m_height)
+	, m_format(that.m_format)
+	, m_bpp(that.m_bpp)
+	, m_palette(nullptr)
+	, m_cliprect(that.m_cliprect)
+{
+	set_palette(that.m_palette);
+	that.reset();
+}
+
 /**
- * @fn  bitmap_t::bitmap_t(bitmap_format format, int bpp, int width, int height, int xslop, int yslop)
+ * @fn  bitmap_t::bitmap_t(bitmap_format format, uint8_t bpp, int width, int height, int xslop, int yslop)
  *
  * @brief   -------------------------------------------------
  *            bitmap_t - basic constructor
@@ -61,19 +77,19 @@ inline void bitmap_t::compute_base(int xslop, int yslop)
  * @param   yslop   The yslop.
  */
 
-bitmap_t::bitmap_t(bitmap_format format, int bpp, int width, int height, int xslop, int yslop)
-	: m_alloc(nullptr),
-		m_allocbytes(0),
-		m_format(format),
-		m_bpp(bpp),
-		m_palette(nullptr)
+bitmap_t::bitmap_t(bitmap_format format, uint8_t bpp, int width, int height, int xslop, int yslop)
+	: m_alloc()
+	, m_allocbytes(0)
+	, m_format(format)
+	, m_bpp(bpp)
+	, m_palette(nullptr)
 {
 	// allocate intializes all other fields
 	allocate(width, height, xslop, yslop);
 }
 
 /**
- * @fn  bitmap_t::bitmap_t(bitmap_format format, int bpp, void *base, int width, int height, int rowpixels)
+ * @fn  bitmap_t::bitmap_t(bitmap_format format, uint8_t bpp, void *base, int width, int height, int rowpixels)
  *
  * @brief   Constructor.
  *
@@ -85,22 +101,22 @@ bitmap_t::bitmap_t(bitmap_format format, int bpp, int width, int height, int xsl
  * @param   rowpixels       The rowpixels.
  */
 
-bitmap_t::bitmap_t(bitmap_format format, int bpp, void *base, int width, int height, int rowpixels)
-	: m_alloc(nullptr),
-		m_allocbytes(0),
-		m_base(base),
-		m_rowpixels(rowpixels),
-		m_width(width),
-		m_height(height),
-		m_format(format),
-		m_bpp(bpp),
-		m_palette(nullptr),
-		m_cliprect(0, width - 1, 0, height - 1)
+bitmap_t::bitmap_t(bitmap_format format, uint8_t bpp, void *base, int width, int height, int rowpixels)
+	: m_alloc()
+	, m_allocbytes(0)
+	, m_base(base)
+	, m_rowpixels(rowpixels)
+	, m_width(width)
+	, m_height(height)
+	, m_format(format)
+	, m_bpp(bpp)
+	, m_palette(nullptr)
+	, m_cliprect(0, width - 1, 0, height - 1)
 {
 }
 
 /**
- * @fn  bitmap_t::bitmap_t(bitmap_format format, int bpp, bitmap_t &source, const rectangle &subrect)
+ * @fn  bitmap_t::bitmap_t(bitmap_format format, uint8_t bpp, bitmap_t &source, const rectangle &subrect)
  *
  * @brief   Constructor.
  *
@@ -110,17 +126,17 @@ bitmap_t::bitmap_t(bitmap_format format, int bpp, void *base, int width, int hei
  * @param   subrect         The subrect.
  */
 
-bitmap_t::bitmap_t(bitmap_format format, int bpp, bitmap_t &source, const rectangle &subrect)
-	: m_alloc(nullptr),
-		m_allocbytes(0),
-		m_base(source.raw_pixptr(subrect.min_y, subrect.min_x)),
-		m_rowpixels(source.m_rowpixels),
-		m_width(subrect.width()),
-		m_height(subrect.height()),
-		m_format(format),
-		m_bpp(bpp),
-		m_palette(nullptr),
-		m_cliprect(0, subrect.width() - 1, 0, subrect.height() - 1)
+bitmap_t::bitmap_t(bitmap_format format, uint8_t bpp, bitmap_t &source, const rectangle &subrect)
+	: m_alloc()
+	, m_allocbytes(0)
+	, m_base(source.raw_pixptr(subrect.min_y, subrect.min_x))
+	, m_rowpixels(source.m_rowpixels)
+	, m_width(subrect.width())
+	, m_height(subrect.height())
+	, m_format(format)
+	, m_bpp(bpp)
+	, m_palette(nullptr)
+	, m_cliprect(0, subrect.width() - 1, 0, subrect.height() - 1)
 {
 	assert(format == source.m_format);
 	assert(bpp == source.m_bpp);
@@ -141,6 +157,22 @@ bitmap_t::~bitmap_t()
 	reset();
 }
 
+bitmap_t &bitmap_t::operator=(bitmap_t &&that)
+{
+	m_alloc = std::move(that.m_alloc);
+	m_allocbytes = that.m_allocbytes;
+	m_base = that.m_base;
+	m_rowpixels = that.m_rowpixels;
+	m_width = that.m_width;
+	m_height = that.m_height;
+	m_format = that.m_format;
+	m_bpp = that.m_bpp;
+	set_palette(that.m_palette);
+	m_cliprect = that.m_cliprect;
+	that.reset();
+	return *this;
+}
+
 /**
  * @fn  void bitmap_t::allocate(int width, int height, int xslop, int yslop)
  *
@@ -175,10 +207,10 @@ void bitmap_t::allocate(int width, int height, int xslop, int yslop)
 
 	// allocate memory for the bitmap itself
 	m_allocbytes = m_rowpixels * (m_height + 2 * yslop) * m_bpp / 8;
-	m_alloc = new uint8_t[m_allocbytes];
+	m_alloc.reset(new uint8_t[m_allocbytes]);
 
 	// clear to 0 by default
-	memset(m_alloc, 0, m_allocbytes);
+	memset(m_alloc.get(), 0, m_allocbytes);
 
 	// compute the base
 	compute_base(xslop, yslop);
@@ -242,8 +274,7 @@ void bitmap_t::reset()
 {
 	// delete any existing stuff
 	set_palette(nullptr);
-	delete[] m_alloc;
-	m_alloc = nullptr;
+	m_alloc.reset();
 	m_base = nullptr;
 
 	// reset all fields
diff --git a/src/lib/util/bitmap.h b/src/lib/util/bitmap.h
index 7d367bc..7b0fc34 100644
--- a/src/lib/util/bitmap.h
+++ b/src/lib/util/bitmap.h
@@ -8,10 +8,10 @@
 
 ***************************************************************************/
 
-#pragma once
+#ifndef MAME_UTIL_BITMAP_H
+#define MAME_UTIL_BITMAP_H
 
-#ifndef __BITMAP_H__
-#define __BITMAP_H__
+#pragma once
 
 #include "osdcore.h"
 #include "palette.h"
@@ -106,10 +106,10 @@ public:
 	void offsety(int32_t delta) { min_y += delta; max_y += delta; }
 
 	// internal state
-	int32_t           min_x;          // minimum X, or left coordinate
-	int32_t           max_x;          // maximum X, or right coordinate (inclusive)
-	int32_t           min_y;          // minimum Y, or top coordinate
-	int32_t           max_y;          // maximum Y, or bottom coordinate (inclusive)
+	int32_t         min_x;          // minimum X, or left coordinate
+	int32_t         max_x;          // maximum X, or right coordinate (inclusive)
+	int32_t         min_y;          // minimum Y, or top coordinate
+	int32_t         max_y;          // maximum Y, or bottom coordinate (inclusive)
 };
 
 
@@ -118,18 +118,19 @@ public:
 // bitmaps describe a rectangular array of pixels
 class bitmap_t
 {
-private:
-	// prevent implicit copying
-	bitmap_t(const bitmap_t &);
-	bitmap_t &operator=(const bitmap_t &);
-
 protected:
 	// construction/destruction -- subclasses only to ensure type correctness
-	bitmap_t(bitmap_format format, int bpp, int width = 0, int height = 0, int xslop = 0, int yslop = 0);
-	bitmap_t(bitmap_format format, int bpp, void *base, int width, int height, int rowpixels);
-	bitmap_t(bitmap_format format, int bpp, bitmap_t &source, const rectangle &subrect);
+	bitmap_t(const bitmap_t &) = delete;
+	bitmap_t(bitmap_t &&that);
+	bitmap_t(bitmap_format format, uint8_t bpp, int width = 0, int height = 0, int xslop = 0, int yslop = 0);
+	bitmap_t(bitmap_format format, uint8_t bpp, void *base, int width, int height, int rowpixels);
+	bitmap_t(bitmap_format format, uint8_t bpp, bitmap_t &source, const rectangle &subrect);
 	virtual ~bitmap_t();
 
+	// prevent implicit copying
+	bitmap_t &operator=(const bitmap_t &) = delete;
+	bitmap_t &operator=(bitmap_t &&that);
+
 public:
 	// allocation/deallocation
 	void reset();
@@ -175,16 +176,16 @@ private:
 	void compute_base(int xslop, int yslop);
 
 	// internal state
-	uint8_t *         m_alloc;        // pointer to allocated pixel memory
-	uint32_t          m_allocbytes;   // size of our allocation
-	void *          m_base;         // pointer to pixel (0,0) (adjusted for padding)
-	int32_t           m_rowpixels;    // pixels per row (including padding)
-	int32_t           m_width;        // width of the bitmap
-	int32_t           m_height;       // height of the bitmap
-	bitmap_format   m_format;       // format of the bitmap
-	uint8_t           m_bpp;          // bits per pixel
-	palette_t *     m_palette;      // optional palette
-	rectangle       m_cliprect;     // a clipping rectangle covering the full bitmap
+	std::unique_ptr<uint8_t []> m_alloc;        // pointer to allocated pixel memory
+	uint32_t                    m_allocbytes;   // size of our allocation
+	void *                      m_base;         // pointer to pixel (0,0) (adjusted for padding)
+	int32_t                     m_rowpixels;    // pixels per row (including padding)
+	int32_t                     m_width;        // width of the bitmap
+	int32_t                     m_height;       // height of the bitmap
+	bitmap_format               m_format;       // format of the bitmap
+	uint8_t                     m_bpp;          // bits per pixel
+	palette_t *                 m_palette;      // optional palette
+	rectangle                   m_cliprect;     // a clipping rectangle covering the full bitmap
 };
 
 
@@ -199,10 +200,13 @@ private:
 
 protected:
 	// construction/destruction -- subclasses only
+	bitmap8_t(bitmap8_t &&) = default;
 	bitmap8_t(bitmap_format format, int width = 0, int height = 0, int xslop = 0, int yslop = 0) : bitmap_t(format, 8, width, height, xslop, yslop) { }
 	bitmap8_t(bitmap_format format, uint8_t *base, int width, int height, int rowpixels) : bitmap_t(format, 8, base, width, height, rowpixels) { assert(valid_format(format)); }
 	bitmap8_t(bitmap_format format, bitmap8_t &source, const rectangle &subrect) : bitmap_t(format, 8, source, subrect) { }
 
+	bitmap8_t &operator=(bitmap8_t &&) = default;
+
 public:
 	// getters
 	uint8_t bpp() const { return 8; }
@@ -222,10 +226,13 @@ private:
 
 protected:
 	// construction/destruction -- subclasses only
+	bitmap16_t(bitmap16_t &&) = default;
 	bitmap16_t(bitmap_format format, int width = 0, int height = 0, int xslop = 0, int yslop = 0) : bitmap_t(format, 16, width, height, xslop, yslop) { assert(valid_format(format)); }
 	bitmap16_t(bitmap_format format, uint16_t *base, int width, int height, int rowpixels) : bitmap_t(format, 16, base, width, height, rowpixels) { assert(valid_format(format)); }
 	bitmap16_t(bitmap_format format, bitmap16_t &source, const rectangle &subrect) : bitmap_t(format, 16, source, subrect) { }
 
+	bitmap16_t &operator=(bitmap16_t &&) = default;
+
 public:
 	// getters
 	uint8_t bpp() const { return 16; }
@@ -245,10 +252,13 @@ private:
 
 protected:
 	// construction/destruction -- subclasses only
+	bitmap32_t(bitmap32_t &&) = default;
 	bitmap32_t(bitmap_format format, int width = 0, int height = 0, int xslop = 0, int yslop = 0) : bitmap_t(format, 32, width, height, xslop, yslop) { assert(valid_format(format)); }
 	bitmap32_t(bitmap_format format, uint32_t *base, int width, int height, int rowpixels) : bitmap_t(format, 32, base, width, height, rowpixels) { assert(valid_format(format)); }
 	bitmap32_t(bitmap_format format, bitmap32_t &source, const rectangle &subrect) : bitmap_t(format, 32, source, subrect) { }
 
+	bitmap32_t &operator=(bitmap32_t &&) = default;
+
 public:
 	// getters
 	uint8_t bpp() const { return 32; }
@@ -268,10 +278,13 @@ private:
 
 protected:
 	// construction/destruction -- subclasses only
+	bitmap64_t(bitmap64_t &&) = default;
 	bitmap64_t(bitmap_format format, int width = 0, int height = 0, int xslop = 0, int yslop = 0) : bitmap_t(format, 64, width, height, xslop, yslop) { assert(valid_format(format)); }
 	bitmap64_t(bitmap_format format, uint64_t *base, int width, int height, int rowpixels) : bitmap_t(format, 64, base, width, height, rowpixels) { assert(valid_format(format)); }
 	bitmap64_t(bitmap_format format, bitmap64_t &source, const rectangle &subrect) : bitmap_t(format, 64, source, subrect) { }
 
+	bitmap64_t &operator=(bitmap64_t &&) = default;
+
 public:
 	// getters
 	uint8_t bpp() const { return 64; }
@@ -292,6 +305,7 @@ class bitmap_ind8 : public bitmap8_t
 
 public:
 	// construction/destruction
+	bitmap_ind8(bitmap_ind8 &&) = default;
 	bitmap_ind8(int width = 0, int height = 0, int xslop = 0, int yslop = 0) : bitmap8_t(k_bitmap_format, width, height, xslop, yslop) { }
 	bitmap_ind8(uint8_t *base, int width, int height, int rowpixels) : bitmap8_t(k_bitmap_format, base, width, height, rowpixels) { }
 	bitmap_ind8(bitmap_ind8 &source, const rectangle &subrect) : bitmap8_t(k_bitmap_format, source, subrect) { }
@@ -300,6 +314,8 @@ public:
 
 	// getters
 	bitmap_format format() const { return k_bitmap_format; }
+
+	bitmap_ind8 &operator=(bitmap_ind8 &&) = default;
 };
 
 // BITMAP_FORMAT_IND16 bitmaps
@@ -309,6 +325,7 @@ class bitmap_ind16 : public bitmap16_t
 
 public:
 	// construction/destruction
+	bitmap_ind16(bitmap_ind16 &&) = default;
 	bitmap_ind16(int width = 0, int height = 0, int xslop = 0, int yslop = 0) : bitmap16_t(k_bitmap_format, width, height, xslop, yslop) { }
 	bitmap_ind16(uint16_t *base, int width, int height, int rowpixels) : bitmap16_t(k_bitmap_format, base, width, height, rowpixels) { }
 	bitmap_ind16(bitmap_ind16 &source, const rectangle &subrect) : bitmap16_t(k_bitmap_format, source, subrect) { }
@@ -317,6 +334,8 @@ public:
 
 	// getters
 	bitmap_format format() const { return k_bitmap_format; }
+
+	bitmap_ind16 &operator=(bitmap_ind16 &&) = default;
 };
 
 // BITMAP_FORMAT_IND32 bitmaps
@@ -326,6 +345,7 @@ class bitmap_ind32 : public bitmap32_t
 
 public:
 	// construction/destruction
+	bitmap_ind32(bitmap_ind32 &&) = default;
 	bitmap_ind32(int width = 0, int height = 0, int xslop = 0, int yslop = 0) : bitmap32_t(k_bitmap_format, width, height, xslop, yslop) { }
 	bitmap_ind32(uint32_t *base, int width, int height, int rowpixels) : bitmap32_t(k_bitmap_format, base, width, height, rowpixels) { }
 	bitmap_ind32(bitmap_ind32 &source, const rectangle &subrect) : bitmap32_t(k_bitmap_format, source, subrect) { }
@@ -334,6 +354,8 @@ public:
 
 	// getters
 	bitmap_format format() const { return k_bitmap_format; }
+
+	bitmap_ind32 &operator=(bitmap_ind32 &&) = default;
 };
 
 // BITMAP_FORMAT_IND64 bitmaps
@@ -343,6 +365,7 @@ class bitmap_ind64 : public bitmap64_t
 
 public:
 	// construction/destruction
+	bitmap_ind64(bitmap_ind64 &&) = default;
 	bitmap_ind64(int width = 0, int height = 0, int xslop = 0, int yslop = 0) : bitmap64_t(k_bitmap_format, width, height, xslop, yslop) { }
 	bitmap_ind64(uint64_t *base, int width, int height, int rowpixels) : bitmap64_t(k_bitmap_format, base, width, height, rowpixels) { }
 	bitmap_ind64(bitmap_ind64 &source, const rectangle &subrect) : bitmap64_t(k_bitmap_format, source, subrect) { }
@@ -351,6 +374,8 @@ public:
 
 	// getters
 	bitmap_format format() const { return k_bitmap_format; }
+
+	bitmap_ind64 &operator=(bitmap_ind64 &&) = default;
 };
 
 
@@ -363,6 +388,7 @@ class bitmap_yuy16 : public bitmap16_t
 
 public:
 	// construction/destruction
+	bitmap_yuy16(bitmap_yuy16 &&) = default;
 	bitmap_yuy16(int width = 0, int height = 0, int xslop = 0, int yslop = 0) : bitmap16_t(k_bitmap_format, width, height, xslop, yslop) { }
 	bitmap_yuy16(uint16_t *base, int width, int height, int rowpixels) : bitmap16_t(k_bitmap_format, base, width, height, rowpixels) { }
 	bitmap_yuy16(bitmap_yuy16 &source, const rectangle &subrect) : bitmap16_t(k_bitmap_format, source, subrect) { }
@@ -371,6 +397,8 @@ public:
 
 	// getters
 	bitmap_format format() const { return k_bitmap_format; }
+
+	bitmap_yuy16 &operator=(bitmap_yuy16 &&) = default;
 };
 
 // BITMAP_FORMAT_RGB32 bitmaps
@@ -380,6 +408,7 @@ class bitmap_rgb32 : public bitmap32_t
 
 public:
 	// construction/destruction
+	bitmap_rgb32(bitmap_rgb32 &&) = default;
 	bitmap_rgb32(int width = 0, int height = 0, int xslop = 0, int yslop = 0) : bitmap32_t(k_bitmap_format, width, height, xslop, yslop) { }
 	bitmap_rgb32(uint32_t *base, int width, int height, int rowpixels) : bitmap32_t(k_bitmap_format, base, width, height, rowpixels) { }
 	bitmap_rgb32(bitmap_rgb32 &source, const rectangle &subrect) : bitmap32_t(k_bitmap_format, source, subrect) { }
@@ -388,6 +417,8 @@ public:
 
 	// getters
 	bitmap_format format() const { return k_bitmap_format; }
+
+	bitmap_rgb32 &operator=(bitmap_rgb32 &&) = default;
 };
 
 // BITMAP_FORMAT_ARGB32 bitmaps
@@ -397,6 +428,7 @@ class bitmap_argb32 : public bitmap32_t
 
 public:
 	// construction/destruction
+	bitmap_argb32(bitmap_argb32 &&) = default;
 	bitmap_argb32(int width = 0, int height = 0, int xslop = 0, int yslop = 0) : bitmap32_t(k_bitmap_format, width, height, xslop, yslop) { }
 	bitmap_argb32(uint32_t *base, int width, int height, int rowpixels) : bitmap32_t(k_bitmap_format, base, width, height, rowpixels) { }
 	bitmap_argb32(bitmap_argb32 &source, const rectangle &subrect) : bitmap32_t(k_bitmap_format, source, subrect) { }
@@ -405,7 +437,9 @@ public:
 
 	// getters
 	bitmap_format format() const { return k_bitmap_format; }
+
+	bitmap_argb32 &operator=(bitmap_argb32 &&) = default;
 };
 
 
-#endif  // __BITMAP_H__
+#endif  // MAME_UTIL_BITMAP_H
diff --git a/src/lib/util/coretmpl.h b/src/lib/util/coretmpl.h
index 758e482..0633a10 100644
--- a/src/lib/util/coretmpl.h
+++ b/src/lib/util/coretmpl.h
@@ -1,5 +1,5 @@
 // license:BSD-3-Clause
-// copyright-holders:Aaron Giles
+// copyright-holders:Aaron Giles, Vas Crabb
 /***************************************************************************
 
     coretmpl.h
@@ -17,9 +17,18 @@
 #include "corealloc.h"
 
 #include <array>
+#include <cassert>
 #include <cstddef>
+#include <functional>
+#include <initializer_list>
 #include <iterator>
+#include <list>
+#include <map>
+#include <memory>
+#include <set>
 #include <stdexcept>
+#include <tuple>
+#include <type_traits>
 #include <utility>
 #include <vector>
 
@@ -433,6 +442,384 @@ private:
 };
 
 
+// LRU cache that behaves like std::map with differences:
+// * drops least-recently used items if necessary on insert to prevent size from exceeding max_size
+// * operator[], at, insert, emplace and find freshen existing entries
+// * iterates from least- to most-recently used rather than in order by key
+// * iterators to dropped items are invalidated
+// * not all map interfaces implemented
+// * copyable and swappable but not movable
+// * swap may invalidate past-the-end iterator, other iterators refer to new container
+template <typename Key, typename T, typename Compare = std::less<Key>, class Allocator = std::allocator<std::pair<Key const, T> > >
+class lru_cache_map
+{
+private:
+	class iterator_compare;
+	typedef std::list<std::pair<Key const, T>, Allocator> value_list;
+	typedef typename std::allocator_traits<Allocator>::template rebind_alloc<typename value_list::iterator> iterator_allocator_type;
+	typedef std::set<typename value_list::iterator, iterator_compare, iterator_allocator_type> iterator_set;
+
+	class iterator_compare
+	{
+	public:
+		typedef std::true_type is_transparent;
+		iterator_compare(Compare const &comp) : m_comp(comp) { }
+		iterator_compare(iterator_compare const &that) = default;
+		iterator_compare(iterator_compare &&that) = default;
+		Compare key_comp() const { return m_comp; }
+		iterator_compare &operator=(iterator_compare const &that) = default;
+		iterator_compare &operator=(iterator_compare &&that) = default;
+		bool operator()(typename value_list::iterator const &lhs, typename value_list::iterator const &rhs) const { return m_comp(lhs->first, rhs->first); }
+		template <typename K> bool operator()(typename value_list::iterator const &lhs, K const &rhs) const { return m_comp(lhs->first, rhs); }
+		template <typename K> bool operator()(K const &lhs, typename value_list::iterator const &rhs) const { return m_comp(lhs, rhs->first); }
+	private:
+		Compare m_comp;
+	};
+
+public:
+	typedef Key key_type;
+	typedef T mapped_type;
+	typedef std::pair<Key const, T> value_type;
+	typedef typename value_list::size_type size_type;
+	typedef typename value_list::difference_type difference_type;
+	typedef Compare key_compare;
+	typedef Allocator allocator_type;
+	typedef value_type &reference;
+	typedef value_type const &const_reference;
+	typedef typename std::allocator_traits<Allocator>::pointer pointer;
+	typedef typename std::allocator_traits<Allocator>::const_pointer const_pointer;
+	typedef typename value_list::iterator iterator;
+	typedef typename value_list::const_iterator const_iterator;
+	typedef typename value_list::reverse_iterator reverse_iterator;
+	typedef typename value_list::const_reverse_iterator const_reverse_iterator;
+
+	explicit lru_cache_map(size_type max_size)
+		: lru_cache_map(max_size, key_compare())
+	{
+	}
+	lru_cache_map(size_type max_size, key_compare const &comp, allocator_type const &alloc = allocator_type())
+		: m_max_size(max_size)
+		, m_size(0U)
+		, m_elements(alloc)
+		, m_mapping(iterator_compare(comp), iterator_allocator_type(alloc))
+	{
+		assert(0U < m_max_size);
+	}
+	lru_cache_map(lru_cache_map const &that)
+		: m_max_size(that.m_max_size)
+		, m_size(that.m_size)
+		, m_elements(that.m_elements)
+		, m_mapping(that.m_mapping.key_comp(), that.m_mapping.get_allocator())
+	{
+		for (iterator it = m_elements.begin(); it != m_elements.end(); ++it)
+			m_mapping.insert(it);
+		assert(m_elements.size() == m_size);
+		assert(m_mapping.size() == m_size);
+	}
+
+	allocator_type get_allocator() const { return m_elements.get_allocator(); }
+
+	iterator begin() { return m_elements.begin(); }
+	const_iterator begin() const { return m_elements.cbegin(); }
+	const_iterator cbegin() const { return m_elements.cbegin(); }
+	iterator end() { return m_elements.end(); }
+	const_iterator end() const { return m_elements.cend(); }
+	const_iterator cend() const { return m_elements.cend(); }
+	reverse_iterator rbegin() { return m_elements.rbegin(); }
+	const_reverse_iterator rbegin() const { return m_elements.crbegin(); }
+	const_reverse_iterator crbegin() const { return m_elements.crbegin(); }
+	reverse_iterator rend() { return m_elements.end(); }
+	const_reverse_iterator rend() const { return m_elements.crend(); }
+	const_reverse_iterator crend() const { return m_elements.crend(); }
+
+	bool empty() const { return !m_size; }
+	size_type size() const { return m_size; }
+	size_type max_size() const { return m_max_size; }
+
+	mapped_type &operator[](key_type const &key)
+	{
+		typename iterator_set::iterator existing(m_mapping.lower_bound(key));
+		if ((m_mapping.end() != existing) && !m_mapping.key_comp()(key, *existing))
+		{
+			m_elements.splice(m_elements.cend(), m_elements, *existing);
+			return (*existing)->second;
+		}
+		make_space(existing);
+		iterator const inserted(m_elements.emplace(m_elements.end(), std::piecewise_construct, std::forward_as_tuple(key), std::tuple<>()));
+		m_mapping.insert(existing, inserted);
+		++m_size;
+		assert(m_elements.size() == m_size);
+		assert(m_mapping.size() == m_size);
+		return inserted->second;
+	}
+	mapped_type &operator[](key_type &&key)
+	{
+		typename iterator_set::iterator existing(m_mapping.lower_bound(key));
+		if ((m_mapping.end() != existing) && !m_mapping.key_comp()(key, *existing))
+		{
+			m_elements.splice(m_elements.cend(), m_elements, *existing);
+			return (*existing)->second;
+		}
+		make_space(existing);
+		iterator const inserted(m_elements.emplace(m_elements.end(), std::piecewise_construct, std::forward_as_tuple(std::move(key)), std::tuple<>()));
+		m_mapping.insert(existing, inserted);
+		++m_size;
+		assert(m_elements.size() == m_size);
+		assert(m_mapping.size() == m_size);
+		return inserted->second;
+	}
+	mapped_type &at(key_type const &key)
+	{
+		typename iterator_set::iterator existing(m_mapping.find(key));
+		if (m_mapping.end() != existing)
+		{
+			m_elements.splice(m_elements.cend(), m_elements, *existing);
+			return (*existing)->second;
+		}
+		else
+		{
+			throw std::out_of_range("lru_cache_map::at");
+		}
+	}
+	mapped_type const &at(key_type const &key) const
+	{
+		typename iterator_set::iterator existing(m_mapping.find(key));
+		if (m_mapping.end() != existing)
+		{
+			m_elements.splice(m_elements.cend(), m_elements, *existing);
+			return (*existing)->second;
+		}
+		else
+		{
+			throw std::out_of_range("lru_cache_map::at");
+		}
+	}
+
+	void clear()
+	{
+		m_size = 0U;
+		m_elements.clear();
+		m_mapping.clear();
+	}
+	std::pair<iterator, bool> insert(value_type const &value)
+	{
+		typename iterator_set::iterator existing(m_mapping.lower_bound(value.first));
+		if ((m_mapping.end() != existing) && !m_mapping.key_comp()(value.first, *existing))
+		{
+			m_elements.splice(m_elements.cend(), m_elements, *existing);
+			return std::pair<iterator, bool>(*existing, false);
+		}
+		make_space(existing);
+		iterator const inserted(m_elements.emplace(m_elements.end(), value));
+		m_mapping.insert(existing, inserted);
+		++m_size;
+		assert(m_elements.size() == m_size);
+		assert(m_mapping.size() == m_size);
+		return std::pair<iterator, bool>(inserted, true);
+	}
+	std::pair<iterator, bool> insert(value_type &&value)
+	{
+		typename iterator_set::iterator existing(m_mapping.lower_bound(value.first));
+		if ((m_mapping.end() != existing) && !m_mapping.key_comp()(value.first, *existing))
+		{
+			m_elements.splice(m_elements.cend(), m_elements, *existing);
+			return std::pair<iterator, bool>(*existing, false);
+		}
+		make_space(existing);
+		iterator const inserted(m_elements.emplace(m_elements.end(), std::move(value)));
+		m_mapping.insert(existing, inserted);
+		++m_size;
+		assert(m_elements.size() == m_size);
+		assert(m_mapping.size() == m_size);
+		return std::pair<iterator, bool>(inserted, true);
+	}
+	template <typename P>
+	std::pair<iterator, bool> insert(P &&value)
+	{
+		// FIXME: should only participate in overload resolution if std::is_constructible<value_type, P&&>::value
+		return emplace(std::forward<P>(value));
+	}
+	template <typename InputIt>
+	void insert(InputIt first, InputIt last)
+	{
+		while (first != last)
+		{
+			insert(*first);
+			++first;
+		}
+	}
+	void insert(std::initializer_list<value_type> ilist)
+	{
+		for (value_type const &value : ilist)
+			insert(value);
+	}
+	template <typename... Params>
+	std::pair<iterator, bool> emplace(Params &&... args)
+	{
+		// TODO: is there a more efficient way than depending on value_type being efficiently movable?
+		return insert(value_type(std::forward<Params>(args)...));
+	}
+	iterator erase(const_iterator pos)
+	{
+		m_mapping.erase(m_elements.erase(pos, pos));
+		iterator const result(m_elements.erase(pos));
+		--m_size;
+		assert(m_elements.size() == m_size);
+		assert(m_mapping.size() == m_size);
+		return result;
+	}
+	iterator erase(const_iterator first, const_iterator last)
+	{
+		iterator pos(m_elements.erase(first, first));
+		while (pos != last)
+		{
+			m_mapping.erase(pos);
+			pos = m_elements.erase(pos);
+			--m_size;
+		}
+		assert(m_elements.size() == m_size);
+		assert(m_mapping.size() == m_size);
+		return pos;
+	}
+	size_type erase(key_type const &key)
+	{
+		typename iterator_set::iterator const found(m_mapping.find(key));
+		if (m_mapping.end() == found)
+		{
+			return 0U;
+		}
+		else
+		{
+			m_elements.erase(*found);
+			m_mapping.erase(found);
+			--m_size;
+			assert(m_elements.size() == m_size);
+			assert(m_mapping.size() == m_size);
+			return 1U;
+		}
+	}
+	void swap(lru_cache_map &that)
+	{
+		using std::swap;
+		swap(m_max_size, that.m_max_size);
+		swap(m_size, that.m_size);
+		swap(m_elements, that.m_elements);
+		swap(m_mapping, that.m_mapping);
+	}
+
+	size_type count(key_type const &key) const
+	{
+		// TODO: perhaps this should freshen an element
+		return m_mapping.count(key);
+	}
+	template <typename K>
+	size_type count(K const &x) const
+	{
+		// FIXME: should only enable this overload if Compare::is_transparent
+		// TODO: perhaps this should freshen an element
+		return m_mapping.count(x);
+	}
+	iterator find(key_type const &key)
+	{
+		typename iterator_set::const_iterator const found(m_mapping.find(key));
+		if (m_mapping.end() == found)
+		{
+			return m_elements.end();
+		}
+		else
+		{
+			m_elements.splice(m_elements.cend(), m_elements, *found);
+			return *found;
+		}
+	}
+	iterator find(key_type const &key) const
+	{
+		typename iterator_set::const_iterator const found(m_mapping.find(key));
+		if (m_mapping.end() == found)
+		{
+			return m_elements.end();
+		}
+		else
+		{
+			m_elements.splice(m_elements.cend(), m_elements, *found);
+			return *found;
+		}
+	}
+	template <typename K>
+	iterator find(K const &x)
+	{
+		// FIXME: should only enable this overload if Compare::is_transparent
+		typename iterator_set::const_iterator const found(m_mapping.find(x));
+		if (m_mapping.end() == found)
+		{
+			return m_elements.end();
+		}
+		else
+		{
+			m_elements.splice(m_elements.cend(), m_elements, *found);
+			return *found;
+		}
+	}
+	template <typename K>
+	iterator find(K const &x) const
+	{
+		// FIXME: should only enable this overload if Compare::is_transparent
+		typename iterator_set::const_iterator const found(m_mapping.find(x));
+		if (m_mapping.end() == found)
+		{
+			return m_elements.end();
+		}
+		else
+		{
+			m_elements.splice(m_elements.cend(), m_elements, *found);
+			return *found;
+		}
+	}
+
+	key_compare key_comp() const
+	{
+		return m_mapping.key_comp().key_comp();
+	}
+
+	lru_cache_map &operator=(lru_cache_map const &that)
+	{
+		m_max_size = that.m_max_size;
+		m_size = that.m_size;
+		m_elements = that.m_elements;
+		m_mapping.clear();
+		for (iterator it = m_elements.begin(); it != m_elements.end(); ++it)
+			m_mapping.insert(it);
+		assert(m_elements.size() == m_size);
+		assert(m_mapping.size() == m_size);
+	}
+
+private:
+	void make_space(typename iterator_set::iterator &existing)
+	{
+		while (m_max_size <= m_size)
+		{
+			if ((m_mapping.end() != existing) && (m_elements.begin() == *existing))
+				existing = m_mapping.erase(existing);
+			else
+				m_mapping.erase(m_elements.begin());
+			m_elements.erase(m_elements.begin());
+			--m_size;
+		}
+	}
+
+	size_type           m_max_size;
+	size_type           m_size;
+	mutable value_list  m_elements;
+	iterator_set        m_mapping;
+};
+
+template <typename Key, typename T, typename Compare, class Allocator>
+void swap(lru_cache_map<Key, T, Compare, Allocator> &lhs, lru_cache_map<Key, T, Compare, Allocator> &rhs)
+{
+	lhs.swap(rhs);
+}
+
+
 template <typename T, std::size_t N, bool WriteWrap = false, bool ReadWrap = WriteWrap>
 class fifo : protected std::array<T, N>
 {
diff --git a/src/lib/util/delegate.h b/src/lib/util/delegate.h
index 5e8f395..f8e23fa 100644
--- a/src/lib/util/delegate.h
+++ b/src/lib/util/delegate.h
@@ -552,7 +552,7 @@ public:
 	bool is_mfp() const { return !m_raw_mfp.isnull(); }
 
 	// late binding
-	void late_bind(delegate_late_bind &object) { bind((*m_latebinder)(object)); }
+	void late_bind(delegate_late_bind &object) { if(m_latebinder) bind((*m_latebinder)(object)); }
 
 protected:
 	// return the actual object (not the one we use for calling)
diff --git a/src/lib/util/xmlfile.cpp b/src/lib/util/xmlfile.cpp
index 458f302..5a6e2d7 100644
--- a/src/lib/util/xmlfile.cpp
+++ b/src/lib/util/xmlfile.cpp
@@ -20,6 +20,8 @@
 #include <cstring>
 
 
+namespace util { namespace xml {
+
 /***************************************************************************
     CONSTANTS
 ***************************************************************************/
@@ -32,12 +34,12 @@
     TYPE DEFINITIONS
 ***************************************************************************/
 
-struct xml_parse_info
+struct parse_info
 {
-	XML_Parser          parser;
-	xml_data_node *     rootnode;
-	xml_data_node *     curnode;
-	uint32_t            flags;
+	XML_Parser      parser;
+	data_node *     rootnode;
+	data_node *     curnode;
+	uint32_t        flags;
 };
 
 
@@ -47,7 +49,7 @@ struct xml_parse_info
 ***************************************************************************/
 
 /* expat interfaces */
-static bool expat_setup_parser(xml_parse_info &info, xml_parse_options const *opts);
+static bool expat_setup_parser(parse_info &info, parse_options const *opts);
 static void expat_element_start(void *data, const XML_Char *name, const XML_Char **attributes);
 static void expat_data(void *data, const XML_Char *s, int len);
 static void expat_element_end(void *data, const XML_Char *name);
@@ -59,25 +61,25 @@ static void expat_element_end(void *data, const XML_Char *name);
 ***************************************************************************/
 
 /*-------------------------------------------------
-    xml_file_create - create a new xml file
+    file_create - create a new xml file
     object
 -------------------------------------------------*/
 
-xml_data_node *xml_data_node::file_create()
+data_node *data_node::file_create()
 {
-	try { return new xml_data_node(); }
+	try { return new data_node(); }
 	catch (...) { return nullptr; }
 }
 
 
 /*-------------------------------------------------
-    xml_file_read - parse an XML file into its
+    file_read - parse an XML file into its
     nodes
 -------------------------------------------------*/
 
-xml_data_node *xml_data_node::file_read(util::core_file &file, xml_parse_options const *opts)
+data_node *data_node::file_read(util::core_file &file, parse_options const *opts)
 {
-	xml_parse_info info;
+	parse_info info;
 	int done;
 
 	/* set up the parser */
@@ -119,13 +121,13 @@ xml_data_node *xml_data_node::file_read(util::core_file &file, xml_parse_options
 
 
 /*-------------------------------------------------
-    xml_string_read - parse an XML string into its
+    string_read - parse an XML string into its
     nodes
 -------------------------------------------------*/
 
-xml_data_node *xml_data_node::string_read(const char *string, xml_parse_options const *opts)
+data_node *data_node::string_read(const char *string, parse_options const *opts)
 {
-	xml_parse_info info;
+	parse_info info;
 	int length = (int)strlen(string);
 
 	/* set up the parser */
@@ -156,10 +158,10 @@ xml_data_node *xml_data_node::string_read(const char *string, xml_parse_options
 
 
 /*-------------------------------------------------
-    xml_file_write - write an XML tree to a file
+    file_write - write an XML tree to a file
 -------------------------------------------------*/
 
-void xml_data_node::file_write(util::core_file &file) const
+void data_node::file_write(util::core_file &file) const
 {
 	/* ensure this is a root node */
 	if (get_name())
@@ -170,16 +172,16 @@ void xml_data_node::file_write(util::core_file &file) const
 	file.printf("<!-- This file is autogenerated; comments and unknown tags will be stripped -->\n");
 
 	/* loop over children of the root and output */
-	for (xml_data_node const *node = get_first_child(); node; node = node->get_next_sibling())
+	for (data_node const *node = get_first_child(); node; node = node->get_next_sibling())
 		node->write_recursive(0, file);
 }
 
 
 /*-------------------------------------------------
-    xml_file_free - free an XML file object
+    file_free - free an XML file object
 -------------------------------------------------*/
 
-void xml_data_node::file_free()
+void data_node::file_free()
 {
 	/* ensure this is a root node */
 	if (get_name())
@@ -194,7 +196,7 @@ void xml_data_node::file_free()
     XML NODE MANAGEMENT
 ***************************************************************************/
 
-xml_data_node::xml_data_node()
+data_node::data_node()
 	: line(0)
 	, m_next(nullptr)
 	, m_first_child(nullptr)
@@ -205,7 +207,7 @@ xml_data_node::xml_data_node()
 {
 }
 
-xml_data_node::xml_data_node(xml_data_node *parent, const char *name, const char *value)
+data_node::data_node(data_node *parent, const char *name, const char *value)
 	: line(0)
 	, m_next(nullptr)
 	, m_first_child(nullptr)
@@ -223,10 +225,10 @@ xml_data_node::xml_data_node(xml_data_node *parent, const char *name, const char
     the data allocated to an XML node
 -------------------------------------------------*/
 
-xml_data_node::~xml_data_node()
+data_node::~data_node()
 {
 	/* free the children */
-	for (xml_data_node *nchild = nullptr; m_first_child; m_first_child = nchild)
+	for (data_node *nchild = nullptr; m_first_child; m_first_child = nchild)
 	{
 		/* note the next node and free this node */
 		nchild = m_first_child->get_next_sibling();
@@ -235,19 +237,19 @@ xml_data_node::~xml_data_node()
 }
 
 
-void xml_data_node::set_value(char const *value)
+void data_node::set_value(char const *value)
 {
 	m_value.assign(value ? value : "");
 }
 
 
-void xml_data_node::append_value(char const *value, int length)
+void data_node::append_value(char const *value, int length)
 {
 	m_value.append(value, length);
 }
 
 
-void xml_data_node::trim_whitespace()
+void data_node::trim_whitespace()
 {
 	/* first strip leading spaces */
 	std::string::iterator start = m_value.begin();
@@ -264,99 +266,99 @@ void xml_data_node::trim_whitespace()
 
 
 /*-------------------------------------------------
-    xml_data_node::count_children - count the
+    data_node::count_children - count the
     number of child nodes
 -------------------------------------------------*/
 
-int xml_data_node::count_children() const
+int data_node::count_children() const
 {
 	int count = 0;
 
 	/* loop over children and count */
-	for (xml_data_node const *node = get_first_child(); node; node = node->get_next_sibling())
+	for (data_node const *node = get_first_child(); node; node = node->get_next_sibling())
 		count++;
 	return count;
 }
 
 
 /*-------------------------------------------------
-    xml_data_node::get_child - find the first
+    data_node::get_child - find the first
     child of the specified node with the specified
     tag
 -------------------------------------------------*/
 
-xml_data_node *xml_data_node::get_child(const char *name)
+data_node *data_node::get_child(const char *name)
 {
 	return m_first_child ? m_first_child->get_sibling(name) : nullptr;
 }
 
-xml_data_node const *xml_data_node::get_child(const char *name) const
+data_node const *data_node::get_child(const char *name) const
 {
 	return m_first_child ? m_first_child->get_sibling(name) : nullptr;
 }
 
 
 /*-------------------------------------------------
-    xml_find_first_matching_child - find the first
+    find_first_matching_child - find the first
     child of the specified node with the
     specified tag or attribute/value pair
 -------------------------------------------------*/
 
-xml_data_node *xml_data_node::find_first_matching_child(const char *name, const char *attribute, const char *matchval)
+data_node *data_node::find_first_matching_child(const char *name, const char *attribute, const char *matchval)
 {
 	return m_first_child ? m_first_child->find_matching_sibling(name, attribute, matchval) : nullptr;
 }
 
-xml_data_node const *xml_data_node::find_first_matching_child(const char *name, const char *attribute, const char *matchval) const
+data_node const *data_node::find_first_matching_child(const char *name, const char *attribute, const char *matchval) const
 {
 	return m_first_child ? m_first_child->find_matching_sibling(name, attribute, matchval) : nullptr;
 }
 
 
 /*-------------------------------------------------
-    xml_data_node::get_next_sibling - find the
+    data_node::get_next_sibling - find the
     next sibling of the specified node with the
     specified tag
 -------------------------------------------------*/
 
-xml_data_node *xml_data_node::get_next_sibling(const char *name)
+data_node *data_node::get_next_sibling(const char *name)
 {
 	return m_next ? m_next->get_sibling(name) : nullptr;
 }
 
-xml_data_node const *xml_data_node::get_next_sibling(const char *name) const
+data_node const *data_node::get_next_sibling(const char *name) const
 {
 	return m_next ? m_next->get_sibling(name) : nullptr;
 }
 
 
 /*-------------------------------------------------
-    xml_find_next_matching_sibling - find the next
+    find_next_matching_sibling - find the next
     sibling of the specified node with the
     specified tag or attribute/value pair
 -------------------------------------------------*/
 
-xml_data_node *xml_data_node::find_next_matching_sibling(const char *name, const char *attribute, const char *matchval)
+data_node *data_node::find_next_matching_sibling(const char *name, const char *attribute, const char *matchval)
 {
 	return m_next ? m_next->find_matching_sibling(name, attribute, matchval) : nullptr;
 }
 
-xml_data_node const *xml_data_node::find_next_matching_sibling(const char *name, const char *attribute, const char *matchval) const
+data_node const *data_node::find_next_matching_sibling(const char *name, const char *attribute, const char *matchval) const
 {
 	return m_next ? m_next->find_matching_sibling(name, attribute, matchval) : nullptr;
 }
 
 
 /*-------------------------------------------------
-    xml_add_child - add a new child node to the
+    add_child - add a new child node to the
     given node
 -------------------------------------------------*/
 
-xml_data_node *xml_data_node::add_child(const char *name, const char *value)
+data_node *data_node::add_child(const char *name, const char *value)
 {
 	/* new element: create a new node */
-	xml_data_node *node;
-	try { node = new xml_data_node(this, name, value); }
+	data_node *node;
+	try { node = new data_node(this, name, value); }
 	catch (...) { return nullptr; }
 
 	if (!node->get_name() || (!node->get_value() && value))
@@ -366,7 +368,7 @@ xml_data_node *xml_data_node::add_child(const char *name, const char *value)
 	}
 
 	/* add us to the end of the list of siblings */
-	xml_data_node **pnode;
+	data_node **pnode;
 	for (pnode = &m_first_child; *pnode; pnode = &(*pnode)->m_next) { }
 	*pnode = node;
 
@@ -375,14 +377,14 @@ xml_data_node *xml_data_node::add_child(const char *name, const char *value)
 
 
 /*-------------------------------------------------
-    xml_get_or_add_child - find a child node of
+    get_or_add_child - find a child node of
     the specified type; if not found, add one
 -------------------------------------------------*/
 
-xml_data_node *xml_data_node::get_or_add_child(const char *name, const char *value)
+data_node *data_node::get_or_add_child(const char *name, const char *value)
 {
 	/* find the child first */
-	xml_data_node *const child = m_first_child->get_sibling(name);
+	data_node *const child = m_first_child->get_sibling(name);
 	if (child)
 		return child;
 
@@ -392,16 +394,16 @@ xml_data_node *xml_data_node::get_or_add_child(const char *name, const char *val
 
 
 /*-------------------------------------------------
-    xml_delete_node - delete a node and its
+    delete_node - delete a node and its
     children
 -------------------------------------------------*/
 
-void xml_data_node::delete_node()
+void data_node::delete_node()
 {
 	/* first unhook us from the list of children of our parent */
 	if (m_parent)
 	{
-		for (xml_data_node **pnode = &m_parent->m_first_child; *pnode; pnode = &(*pnode)->m_next)
+		for (data_node **pnode = &m_parent->m_first_child; *pnode; pnode = &(*pnode)->m_next)
 		{
 			if (*pnode == this)
 			{
@@ -417,23 +419,23 @@ void xml_data_node::delete_node()
 
 
 /*-------------------------------------------------
-    xml_get_next_sibling - find the next sibling of
+    get_next_sibling - find the next sibling of
     the specified node with the specified tag
 -------------------------------------------------*/
 
-xml_data_node *xml_data_node::get_sibling(const char *name)
+data_node *data_node::get_sibling(const char *name)
 {
 	/* loop over siblings and find a matching name */
-	for (xml_data_node *node = this; node; node = node->get_next_sibling())
+	for (data_node *node = this; node; node = node->get_next_sibling())
 		if (strcmp(node->get_name(), name) == 0)
 			return node;
 	return nullptr;
 }
 
-xml_data_node const *xml_data_node::get_sibling(const char *name) const
+data_node const *data_node::get_sibling(const char *name) const
 {
 	/* loop over siblings and find a matching name */
-	for (xml_data_node const *node = this; node; node = node->get_next_sibling())
+	for (data_node const *node = this; node; node = node->get_next_sibling())
 		if (strcmp(node->get_name(), name) == 0)
 			return node;
 	return nullptr;
@@ -441,15 +443,15 @@ xml_data_node const *xml_data_node::get_sibling(const char *name) const
 
 
 /*-------------------------------------------------
-    xml_find_matching_sibling - find the next
+    find_matching_sibling - find the next
     sibling of the specified node with the
     specified tag or attribute/value pair
 -------------------------------------------------*/
 
-xml_data_node *xml_data_node::find_matching_sibling(const char *name, const char *attribute, const char *matchval)
+data_node *data_node::find_matching_sibling(const char *name, const char *attribute, const char *matchval)
 {
 	/* loop over siblings and find a matching attribute */
-	for (xml_data_node *node = this; node; node = node->get_next_sibling())
+	for (data_node *node = this; node; node = node->get_next_sibling())
 	{
 		/* can pass nullptr as a wildcard for the node name */
 		if (!name || !strcmp(name, node->get_name()))
@@ -463,10 +465,10 @@ xml_data_node *xml_data_node::find_matching_sibling(const char *name, const char
 	return nullptr;
 }
 
-xml_data_node const *xml_data_node::find_matching_sibling(const char *name, const char *attribute, const char *matchval) const
+data_node const *data_node::find_matching_sibling(const char *name, const char *attribute, const char *matchval) const
 {
 	/* loop over siblings and find a matching attribute */
-	for (xml_data_node const *node = this; node; node = node->get_next_sibling())
+	for (data_node const *node = this; node; node = node->get_next_sibling())
 	{
 		/* can pass nullptr as a wildcard for the node name */
 		if (!name || !strcmp(name, node->get_name()))
@@ -486,18 +488,18 @@ xml_data_node const *xml_data_node::find_matching_sibling(const char *name, cons
     XML ATTRIBUTE MANAGEMENT
 ***************************************************************************/
 
-bool xml_data_node::has_attribute(const char *attribute) const
+bool data_node::has_attribute(const char *attribute) const
 {
 	return get_attribute(attribute) != nullptr;
 }
 
 
 /*-------------------------------------------------
-    xml_get_attribute - get the value of the
+    get_attribute - get the value of the
     specified attribute, or nullptr if not found
 -------------------------------------------------*/
 
-xml_data_node::attribute_node *xml_data_node::get_attribute(const char *attribute)
+data_node::attribute_node *data_node::get_attribute(const char *attribute)
 {
 	/* loop over attributes and find a match */
 	for (attribute_node &anode : m_attributes)
@@ -506,7 +508,7 @@ xml_data_node::attribute_node *xml_data_node::get_attribute(const char *attribut
 	return nullptr;
 }
 
-xml_data_node::attribute_node const *xml_data_node::get_attribute(const char *attribute) const
+data_node::attribute_node const *data_node::get_attribute(const char *attribute) const
 {
 	/* loop over attributes and find a match */
 	for (attribute_node const &anode : m_attributes)
@@ -517,12 +519,12 @@ xml_data_node::attribute_node const *xml_data_node::get_attribute(const char *at
 
 
 /*-------------------------------------------------
-    xml_get_attribute_string - get the string
+    get_attribute_string - get the string
     value of the specified attribute; if not
     found, return = the provided default
 -------------------------------------------------*/
 
-const char *xml_data_node::get_attribute_string(const char *attribute, const char *defvalue) const
+const char *data_node::get_attribute_string(const char *attribute, const char *defvalue) const
 {
 	attribute_node const *attr = get_attribute(attribute);
 	return attr ? attr->value.c_str() : defvalue;
@@ -530,12 +532,12 @@ const char *xml_data_node::get_attribute_string(const char *attribute, const cha
 
 
 /*-------------------------------------------------
-    xml_get_attribute_int - get the integer
+    get_attribute_int - get the integer
     value of the specified attribute; if not
     found, return = the provided default
 -------------------------------------------------*/
 
-int xml_data_node::get_attribute_int(const char *attribute, int defvalue) const
+int data_node::get_attribute_int(const char *attribute, int defvalue) const
 {
 	char const *const string = get_attribute_string(attribute, nullptr);
 	int value;
@@ -554,11 +556,11 @@ int xml_data_node::get_attribute_int(const char *attribute, int defvalue) const
 
 
 /*-------------------------------------------------
-    xml_get_attribute_int_format - return the
+    get_attribute_int_format - return the
     format of the given integer attribute
 -------------------------------------------------*/
 
-xml_data_node::int_format xml_data_node::get_attribute_int_format(const char *attribute) const
+data_node::int_format data_node::get_attribute_int_format(const char *attribute) const
 {
 	char const *const string = get_attribute_string(attribute, nullptr);
 
@@ -576,12 +578,12 @@ xml_data_node::int_format xml_data_node::get_attribute_int_format(const char *at
 
 
 /*-------------------------------------------------
-    xml_get_attribute_float - get the float
+    get_attribute_float - get the float
     value of the specified attribute; if not
     found, return = the provided default
 -------------------------------------------------*/
 
-float xml_data_node::get_attribute_float(const char *attribute, float defvalue) const
+float data_node::get_attribute_float(const char *attribute, float defvalue) const
 {
 	char const *const string = get_attribute_string(attribute, nullptr);
 	float value;
@@ -593,11 +595,11 @@ float xml_data_node::get_attribute_float(const char *attribute, float defvalue)
 
 
 /*-------------------------------------------------
-    xml_set_attribute - set a new attribute and
+    set_attribute - set a new attribute and
     string value on the node
 -------------------------------------------------*/
 
-void xml_data_node::set_attribute(const char *name, const char *value)
+void data_node::set_attribute(const char *name, const char *value)
 {
 	attribute_node *anode;
 
@@ -618,11 +620,11 @@ void xml_data_node::set_attribute(const char *name, const char *value)
 
 
 /*-------------------------------------------------
-    xml_set_attribute_int - set a new attribute and
+    set_attribute_int - set a new attribute and
     integer value on the node
 -------------------------------------------------*/
 
-void xml_data_node::set_attribute_int(const char *name, int value)
+void data_node::set_attribute_int(const char *name, int value)
 {
 	char buffer[100];
 	sprintf(buffer, "%d", value);
@@ -631,11 +633,11 @@ void xml_data_node::set_attribute_int(const char *name, int value)
 
 
 /*-------------------------------------------------
-    xml_set_attribute_int - set a new attribute and
+    set_attribute_int - set a new attribute and
     float value on the node
 -------------------------------------------------*/
 
-void xml_data_node::set_attribute_float(const char *name, float value)
+void data_node::set_attribute_float(const char *name, float value)
 {
 	char buffer[100];
 	sprintf(buffer, "%f", (double) value);
@@ -649,11 +651,11 @@ void xml_data_node::set_attribute_float(const char *name, float value)
 ***************************************************************************/
 
 /*-------------------------------------------------
-    xml_normalize_string - normalize a string
+    normalize_string - normalize a string
     to ensure it doesn't contain embedded tags
 -------------------------------------------------*/
 
-const char *xml_normalize_string(const char *string)
+const char *normalize_string(const char *string)
 {
 	static char buffer[1024];
 	char *d = &buffer[0];
@@ -723,7 +725,7 @@ static void *expat_realloc(void *ptr, size_t size)
     expat_setup_parser - set up expat for parsing
 -------------------------------------------------*/
 
-static bool expat_setup_parser(xml_parse_info &info, xml_parse_options const *opts)
+static bool expat_setup_parser(parse_info &info, parse_options const *opts)
 {
 	XML_Memory_Handling_Suite memcallbacks;
 
@@ -741,7 +743,7 @@ static bool expat_setup_parser(xml_parse_info &info, xml_parse_options const *op
 	}
 
 	/* create a root node */
-	info.rootnode = xml_data_node::file_create();
+	info.rootnode = data_node::file_create();
 	if (info.rootnode == nullptr)
 		return false;
 	info.curnode = info.rootnode;
@@ -776,9 +778,9 @@ static bool expat_setup_parser(xml_parse_info &info, xml_parse_options const *op
 
 static void expat_element_start(void *data, const XML_Char *name, const XML_Char **attributes)
 {
-	xml_parse_info *parse_info = (xml_parse_info *) data;
-	xml_data_node **curnode = &parse_info->curnode;
-	xml_data_node *newnode;
+	parse_info *info = (parse_info *) data;
+	data_node **curnode = &info->curnode;
+	data_node *newnode;
 	int attr;
 
 	/* add a new child node to the current node */
@@ -787,7 +789,7 @@ static void expat_element_start(void *data, const XML_Char *name, const XML_Char
 		return;
 
 	/* remember the line number */
-	newnode->line = XML_GetCurrentLineNumber(parse_info->parser);
+	newnode->line = XML_GetCurrentLineNumber(info->parser);
 
 	/* add all the attributes as well */
 	for (attr = 0; attributes[attr]; attr += 2)
@@ -805,8 +807,8 @@ static void expat_element_start(void *data, const XML_Char *name, const XML_Char
 
 static void expat_data(void *data, const XML_Char *s, int len)
 {
-	xml_parse_info *parse_info = (xml_parse_info *) data;
-	xml_data_node **curnode = &parse_info->curnode;
+	parse_info *info = (parse_info *) data;
+	data_node **curnode = &info->curnode;
 	(*curnode)->append_value(s, len);
 }
 
@@ -818,11 +820,11 @@ static void expat_data(void *data, const XML_Char *s, int len)
 
 static void expat_element_end(void *data, const XML_Char *name)
 {
-	xml_parse_info *parse_info = (xml_parse_info *) data;
-	xml_data_node **curnode = &parse_info->curnode;
+	parse_info *info = (parse_info *) data;
+	data_node **curnode = &info->curnode;
 
 	/* strip leading/trailing spaces from the value data */
-	if (!(parse_info->flags & XML_PARSE_FLAG_WHITESPACE_SIGNIFICANT))
+	if (!(info->flags & PARSE_FLAG_WHITESPACE_SIGNIFICANT))
 		(*curnode)->trim_whitespace();
 
 	/* back us up a node */
@@ -840,7 +842,7 @@ static void expat_element_end(void *data, const XML_Char *name)
     given node
 -------------------------------------------------*/
 
-void xml_data_node::add_attribute(const char *name, const char *value)
+void data_node::add_attribute(const char *name, const char *value)
 {
 	try
 	{
@@ -863,7 +865,7 @@ void xml_data_node::add_attribute(const char *name, const char *value)
     an XML node and its children to a file
 -------------------------------------------------*/
 
-void xml_data_node::write_recursive(int indent, util::core_file &file) const
+void data_node::write_recursive(int indent, util::core_file &file) const
 {
 	/* output this tag */
 	file.printf("%*s<%s", indent, "", get_name());
@@ -889,7 +891,7 @@ void xml_data_node::write_recursive(int indent, util::core_file &file) const
 		/* loop over children and output them as well */
 		if (get_first_child())
 		{
-			for (xml_data_node const *child = this->get_first_child(); child; child = child->get_next_sibling())
+			for (data_node const *child = this->get_first_child(); child; child = child->get_next_sibling())
 				child->write_recursive(indent + 4, file);
 		}
 
@@ -897,3 +899,6 @@ void xml_data_node::write_recursive(int indent, util::core_file &file) const
 		file.printf("%*s</%s>\n", indent, "", get_name());
 	}
 }
+
+
+} } // namespace util::xml
diff --git a/src/lib/util/xmlfile.h b/src/lib/util/xmlfile.h
index e6d3397..c8f8c4a 100644
--- a/src/lib/util/xmlfile.h
+++ b/src/lib/util/xmlfile.h
@@ -21,26 +21,29 @@
 #include <utility>
 
 
+// forward type declarations
+struct XML_ParserStruct;
+
+
+namespace util { namespace xml {
+
 /***************************************************************************
     CONSTANTS
 ***************************************************************************/
 
 enum
 {
-	XML_PARSE_FLAG_WHITESPACE_SIGNIFICANT = 1
+	PARSE_FLAG_WHITESPACE_SIGNIFICANT = 1
 };
 
 
+
 /***************************************************************************
     TYPE DEFINITIONS
 ***************************************************************************/
 
-// forward type declarations
-struct XML_ParserStruct;
-
-
 /* extended error information from parsing */
-struct xml_parse_error
+struct parse_error
 {
 	const char *            error_message;
 	int                     error_line;
@@ -49,16 +52,16 @@ struct xml_parse_error
 
 
 // parsing options
-struct xml_parse_options
+struct parse_options
 {
-	xml_parse_error *       error;
-	void                    (*init_parser)(struct XML_ParserStruct *parser);
-	uint32_t                flags;
+	parse_error *       error;
+	void                (*init_parser)(XML_ParserStruct *parser);
+	uint32_t            flags;
 };
 
 
 // a node representing a data item and its relationships
-class xml_data_node
+class data_node
 {
 public:
 	enum class int_format
@@ -74,13 +77,13 @@ public:
 	/* ----- XML file objects ----- */
 
 	// create a new empty xml file object
-	static xml_data_node *file_create();
+	static data_node *file_create();
 
 	// parse an XML file into its nodes */
-	static xml_data_node *file_read(util::core_file &file, xml_parse_options const *opts);
+	static data_node *file_read(util::core_file &file, parse_options const *opts);
 
 	/* parse an XML string into its nodes */
-	static xml_data_node *string_read(const char *string, xml_parse_options const *opts);
+	static data_node *string_read(const char *string, parse_options const *opts);
 
 	// write an XML tree to a file
 	void file_write(util::core_file &file) const;
@@ -98,41 +101,41 @@ public:
 	void append_value(char const *value, int length);
 	void trim_whitespace();
 
-	xml_data_node *get_parent() { return m_parent; }
-	xml_data_node const *get_parent() const { return m_parent; }
+	data_node *get_parent() { return m_parent; }
+	data_node const *get_parent() const { return m_parent; }
 
 	// count the number of child nodes
 	int count_children() const;
 
 	// get the first child
-	xml_data_node *get_first_child() { return m_first_child; }
-	xml_data_node const *get_first_child() const { return m_first_child; }
+	data_node *get_first_child() { return m_first_child; }
+	data_node const *get_first_child() const { return m_first_child; }
 
 	// find the first child with the given tag
-	xml_data_node *get_child(const char *name);
-	xml_data_node const *get_child(const char *name) const;
+	data_node *get_child(const char *name);
+	data_node const *get_child(const char *name) const;
 
 	// find the first child with the given tag and/or attribute/value pair
-	xml_data_node *find_first_matching_child(const char *name, const char *attribute, const char *matchval);
-	xml_data_node const *find_first_matching_child(const char *name, const char *attribute, const char *matchval) const;
+	data_node *find_first_matching_child(const char *name, const char *attribute, const char *matchval);
+	data_node const *find_first_matching_child(const char *name, const char *attribute, const char *matchval) const;
 
 	// get the next sibling
-	xml_data_node *get_next_sibling() { return m_next; }
-	xml_data_node const *get_next_sibling() const { return m_next; }
+	data_node *get_next_sibling() { return m_next; }
+	data_node const *get_next_sibling() const { return m_next; }
 
 	// find the next sibling with the given tag
-	xml_data_node *get_next_sibling(const char *name);
-	xml_data_node const *get_next_sibling(const char *name) const;
+	data_node *get_next_sibling(const char *name);
+	data_node const *get_next_sibling(const char *name) const;
 
 	// find the next sibling with the given tag and/or attribute/value pair
-	xml_data_node *find_next_matching_sibling(const char *name, const char *attribute, const char *matchval);
-	xml_data_node const *find_next_matching_sibling(const char *name, const char *attribute, const char *matchval) const;
+	data_node *find_next_matching_sibling(const char *name, const char *attribute, const char *matchval);
+	data_node const *find_next_matching_sibling(const char *name, const char *attribute, const char *matchval) const;
 
 	// add a new child node
-	xml_data_node *add_child(const char *name, const char *value);
+	data_node *add_child(const char *name, const char *value);
 
 	// either return an existing child node or create one if it doesn't exist
-	xml_data_node *get_or_add_child(const char *name, const char *value);
+	data_node *get_or_add_child(const char *name, const char *value);
 
 	// delete a node and its children
 	void delete_node();
@@ -184,19 +187,19 @@ private:
 	};
 
 
-	xml_data_node();
-	xml_data_node(xml_data_node *parent, const char *name, const char *value);
-	~xml_data_node();
+	data_node();
+	data_node(data_node *parent, const char *name, const char *value);
+	~data_node();
 
-	xml_data_node(xml_data_node const &) = delete;
-	xml_data_node(xml_data_node &&) = delete;
-	xml_data_node &operator=(xml_data_node &&) = delete;
-	xml_data_node &operator=(xml_data_node const &) = delete;
+	data_node(data_node const &) = delete;
+	data_node(data_node &&) = delete;
+	data_node &operator=(data_node &&) = delete;
+	data_node &operator=(data_node const &) = delete;
 
-	xml_data_node *get_sibling(const char *name);
-	xml_data_node const *get_sibling(const char *name) const;
-	xml_data_node *find_matching_sibling(const char *name, const char *attribute, const char *matchval);
-	xml_data_node const *find_matching_sibling(const char *name, const char *attribute, const char *matchval) const;
+	data_node *get_sibling(const char *name);
+	data_node const *get_sibling(const char *name) const;
+	data_node *find_matching_sibling(const char *name, const char *attribute, const char *matchval);
+	data_node const *find_matching_sibling(const char *name, const char *attribute, const char *matchval) const;
 
 	attribute_node *get_attribute(const char *attribute);
 	attribute_node const *get_attribute(const char *attribute) const;
@@ -204,11 +207,11 @@ private:
 	void write_recursive(int indent, util::core_file &file) const;
 
 
-	xml_data_node *             m_next;
-	xml_data_node *             m_first_child;
+	data_node *                 m_next;
+	data_node *                 m_first_child;
 	std::string                 m_name;
 	std::string                 m_value;
-	xml_data_node *             m_parent;
+	data_node *                 m_parent;
 	std::list<attribute_node>   m_attributes;
 };
 
@@ -221,6 +224,8 @@ private:
 /* ----- miscellaneous interfaces ----- */
 
 /* normalize a string into something that can be written to an XML file */
-const char *xml_normalize_string(const char *string);
+const char *normalize_string(const char *string);
+
+} } // namespace util::xml
 
 #endif  /* MAME_LIB_UTIL_XMLFILE_H */
diff --git a/src/mame/arcade.flt b/src/mame/arcade.flt
index fe6ed0c..5fdab2a 100644
--- a/src/mame/arcade.flt
+++ b/src/mame/arcade.flt
@@ -850,6 +850,7 @@ peplus.cpp
 peyper.cpp
 pgm.cpp
 pgm2.cpp
+pgm3.cpp
 phoenix.cpp
 photon.cpp
 photon2.cpp
@@ -1329,6 +1330,7 @@ zerozone.cpp
 zn.cpp
 zodiack.cpp
 zr107.cpp
+zwackery.cpp
 //exceptions + to add - to remove from imported list
 //3do.cpp
 -3do
diff --git a/src/mame/audio/8080bw.cpp b/src/mame/audio/8080bw.cpp
index 6b13793..8928b14 100644
--- a/src/mame/audio/8080bw.cpp
+++ b/src/mame/audio/8080bw.cpp
@@ -66,6 +66,7 @@ WRITE8_MEMBER(_8080bw_state::invadpt2_sh_port_2_w)
 	if (rising_bits & 0x10) m_samples->start(3, 7);     /* SAUCER HIT */
 
 	m_flip_screen = BIT(data, 5) & ioport(CABINET_PORT_TAG)->read();
+	m_color_map = BIT(data, 5);
 
 	m_port_2_last_extra = data;
 }
diff --git a/src/mame/audio/beezer.cpp b/src/mame/audio/beezer.cpp
deleted file mode 100644
index a2a19a2..0000000
--- a/src/mame/audio/beezer.cpp
+++ /dev/null
@@ -1,482 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Mathis Rosenhauer
-/*************************************************************************
-
-    Beezer 6522+6840 audio hardware
-    driver based on exidy audio hardware which it shares some similarity to
-    Original driver by ? (Nicola or Aaron, I think)
-    Preliminary, partially functional driver by Jonathan Gevaryahu
-    AKA Lord Nightmare
-
-    TODO:
-    * Several inexplicable things on the schematic are not handled, such as the
-     'VCO' input for 6840 channel 2 external clock whose source does not appear
-     anywhere on the schematic, nor does it handle the 'DMOD DATA' and 'DMOD
-     CLR' outputs for some sort of digital modulator (perhaps an hc55516?)
-     from the VIA, which also does not appear anywhere on schematic.
-     The latter the VIA *DOES* seem to write something to, but it may be just
-     a silence waveform for 55516, alternating zeroes and ones.
-    * The channel mixing is done additively at the moment rather than
-     emulating the original multiplexer, which is actually not that hard to do
-     but adds a bit of complexity to the render loop.
-    * The 'FM OR AM' output of the audio via (pb1) appears to control some sort
-     of suppression or filtering change of the post-DAC amplifier when enabled,
-     only during the TIMER1 OUT time-slot of the multiplexer, see page 1B 3-3
-     of schematics. This will be a MESS to emulate since theres a lot of analog
-     crap involved.
-    * The /INT line and related logic of the 6840 is not emulated, and should
-     be hooked to the audio 6809.
-    * Convert this to a modern device instead of a deprecated old style device
-
-
-    Notes on multiplexer:
-    The sound output is from a DAC76xx 8-bit dac; driving this dac is a pair
-     of 74ls670 4x4 register files wired up as four 8-bit words;
-     The four words are used as the volumes for four 1-bit channels by inversion
-     of the MSB of the 8 bit value.
-    NOISE is the output of an MM5837 whitenoise generator, a self-clocked (at
-     around 100khz) LFSR with taps on bits (base-0) 16 and 13.
-    The four channels are:
-    CNT1 CNT0
-    0    0    6522 pin 7 output (squarewave); 'FM or AM' affects this slot only
-    0    1    6840 channel 1 clocked by E1(int) OR by 6522 PB7-latched NOISE
-    1    0    6840 channel 2 clocked by E1(int) OR by "VCO" ext (Huh?)
-    1    1    6840 channel 3 clocked by E1(int) OR by channel 2-latched NOISE
-
-    The four slots determine which address is selected of the 8-bit words and
-     which source will XOR against the MSB of the 8-bit word before it goes
-     to the DAC (effectively making the 8-bit word be a 7-bit volume control
-     plus optional wave invert). The speed which cnt0 and cnt1 count at is
-     E1/16 or 62500Hz.
-
-*************************************************************************/
-
-#include "emu.h"
-#include "machine/rescap.h"
-#include "includes/beezer.h"
-
-
-/*************************************
- *
- *  Constants
- *
- *************************************/
-
-#define CRYSTAL_OSC             (XTAL_12MHz)
-#define SH6840_CLOCK            (CRYSTAL_OSC / 12)
-#define MULTIPLEX_FREQ          (SH6840_CLOCK / 16)
-
-
-const device_type BEEZER = &device_creator<beezer_sound_device>;
-
-beezer_sound_device::beezer_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
-	: device_t(mconfig, BEEZER, "beezer SFX", tag, owner, clock, "beezer_sound", __FILE__),
-		device_sound_interface(mconfig, *this),
-		//m_ptm_irq_state(0),
-		m_sh6840_MSB_latch(0),
-		m_sh6840_LSB_latch(0),
-		m_sh6840_LFSR(0),
-		m_sh6840_LFSR_clocks(0),
-		m_sh6840_clocks_per_sample(0),
-		m_sh6840_clock_count(0),
-		m_sh6840_latchwrite(0),
-		m_sh6840_latchwriteold(0),
-		m_sh6840_noiselatch1(0),
-		m_sh6840_noiselatch3(0),
-		m_stream(nullptr)/*,
-		m_freq_to_step(0)*/
-{
-	memset(m_sh6840_timer, 0, sizeof(m_sh6840_timer));
-	m_sh6840_volume[0] = 0;
-	m_sh6840_volume[1] = 0;
-	m_sh6840_volume[2] = 0;
-	m_sh6840_volume[3] = 0;
-}
-
-//-------------------------------------------------
-//  device_config_complete - perform any
-//  operations now that the configuration is
-//  complete
-//-------------------------------------------------
-
-void beezer_sound_device::device_config_complete()
-{
-}
-
-//-------------------------------------------------
-//  device_start - device-specific startup
-//-------------------------------------------------
-
-void beezer_sound_device::device_start()
-{
-	int sample_rate = MULTIPLEX_FREQ;
-
-	m_sh6840_clocks_per_sample = (int)(((double)SH6840_CLOCK / (double)sample_rate) * (double)(1 << 24));
-
-	/* allocate the stream */
-	m_stream = machine().sound().stream_alloc(*this, 0, 1, sample_rate);
-	m_maincpu = machine().device<cpu_device>("maincpu");
-
-	save_item(NAME(m_sh6840_volume));
-	save_item(NAME(m_sh6840_MSB_latch));
-	save_item(NAME(m_sh6840_LSB_latch));
-	save_item(NAME(m_sh6840_LFSR));
-	save_item(NAME(m_sh6840_LFSR_clocks));
-	save_item(NAME(m_sh6840_clock_count));
-	save_item(NAME(m_sh6840_latchwrite));
-	save_item(NAME(m_sh6840_latchwriteold));
-	save_item(NAME(m_sh6840_noiselatch1));
-	save_item(NAME(m_sh6840_noiselatch3));
-	save_item(NAME(m_sh6840_timer[0].cr));
-	save_item(NAME(m_sh6840_timer[0].state));
-	save_item(NAME(m_sh6840_timer[0].leftovers));
-	save_item(NAME(m_sh6840_timer[0].timer));
-	save_item(NAME(m_sh6840_timer[0].clocks));
-	save_item(NAME(m_sh6840_timer[0].counter.w));
-	save_item(NAME(m_sh6840_timer[1].cr));
-	save_item(NAME(m_sh6840_timer[1].state));
-	save_item(NAME(m_sh6840_timer[1].leftovers));
-	save_item(NAME(m_sh6840_timer[1].timer));
-	save_item(NAME(m_sh6840_timer[1].clocks));
-	save_item(NAME(m_sh6840_timer[1].counter.w));
-	save_item(NAME(m_sh6840_timer[2].cr));
-	save_item(NAME(m_sh6840_timer[2].state));
-	save_item(NAME(m_sh6840_timer[2].leftovers));
-	save_item(NAME(m_sh6840_timer[2].timer));
-	save_item(NAME(m_sh6840_timer[2].clocks));
-	save_item(NAME(m_sh6840_timer[2].counter.w));
-}
-
-//-------------------------------------------------
-//  device_reset - device-specific reset
-//-------------------------------------------------
-
-void beezer_sound_device::device_reset()
-{
-	/* 6840 */
-	memset(m_sh6840_timer, 0, sizeof(m_sh6840_timer));
-	m_sh6840_MSB_latch = 0;
-	m_sh6840_LSB_latch = 0;
-	m_sh6840_volume[0] = 0;
-	m_sh6840_volume[1] = 0;
-	m_sh6840_volume[2] = 0;
-	m_sh6840_volume[3] = 0;
-	m_sh6840_clock_count = 0;
-	m_sh6840_latchwrite = 0;
-	m_sh6840_latchwriteold = 0;
-	m_sh6840_noiselatch1 = 0;
-	m_sh6840_noiselatch3 = 0;
-
-	/* LFSR */
-	m_sh6840_LFSR = 0xffffffff;
-	m_sh6840_LFSR_clocks = 0;
-}
-
-
-/*************************************
- *
- *  Interrupt generation helper
- *  TODO: make this actually do something useful
- *************************************/
-
-/*WRITE_LINE_MEMBER( beezer_sound_device::update_irq_state )
-{
-    m_audiocpu->set_input_line(M6809_IRQ_LINE, (sndptm_irq_state) ? ASSERT_LINE : CLEAR_LINE);
-}*/
-
-
-
-/*************************************
- *
- *  6840 clock counting helper
- *
- *************************************/
-// need to set int_flag properly here
-static inline void sh6840_apply_clock(struct sh6840_timer_channel_beez *t, int clocks)
-{
-	/* dual 8-bit case */
-	if (t->cr & 0x04)
-	{
-		/* handle full decrements */
-		while (clocks > t->counter.b.l)
-		{
-			clocks -= t->counter.b.l + 1;
-			t->counter.b.l = t->timer;
-
-			/* decrement MSB */
-			if (!t->counter.b.h--)
-			{
-				t->state = 0;
-				t->counter.w = t->timer;
-			}
-
-			/* state goes high when MSB is 0 */
-			else if (!t->counter.b.h)
-			{
-				t->state = 1;
-				t->clocks++;
-			}
-		}
-
-		/* subtract off the remainder */
-		t->counter.b.l -= clocks;
-	}
-
-	/* 16-bit case */
-	else
-	{
-		/* handle full decrements */
-		while (clocks > t->counter.w)
-		{
-			clocks -= t->counter.w + 1;
-			t->state ^= 1;
-			t->clocks += t->state;
-			t->counter.w = t->timer;
-		}
-
-		/* subtract off the remainder */
-		t->counter.w -= clocks;
-	}
-}
-
-
-
-/*************************************
- *
- *  Noise generation helper
- *
- *************************************/
-
-int beezer_sound_device::sh6840_update_noise(int clocks)
-{
-	uint32_t newxor;
-	int noise_clocks = 0;
-	int i;
-
-	/* loop over clocks */
-	for (i = 0; i < clocks; i++)
-	{
-		m_sh6840_LFSR_clocks++;
-		if (m_sh6840_LFSR_clocks >= 10) // about 10 clocks per 6840 clock, as MM5837 runs at around 100kHz, while clock is 1MHz
-		{
-			m_sh6840_LFSR_clocks = 0;
-			/* shift the LFSR. finally or in the result and see if we've
-			* had a 0->1 transition */
-			newxor = (((m_sh6840_LFSR&0x10000)?1:0) ^ ((m_sh6840_LFSR&0x2000)?1:0))?1:0;
-			m_sh6840_LFSR <<= 1;
-			m_sh6840_LFSR |= newxor;
-			/*printf("LFSR: %4x, %4x, %4x, %4x\n", sh6840_LFSR_3, sh6840_LFSR_2, sh6840_LFSR_1, sh6840_LFSR_0);*/
-			/* if we clocked 0->1, that will serve as an external clock */
-			if ((m_sh6840_LFSR & 0x01) == 0x01) /* tap is at bit 0, GUESSED */
-			{
-				noise_clocks++;
-			}
-		}
-	}
-	return noise_clocks;
-}
-
-
-/*************************************
- *
- *  6840 timer handlers
- *
- *************************************/
-
-READ8_MEMBER( beezer_sound_device::sh6840_r )
-{
-	/* force an update of the stream */
-	m_stream->update();
-
-	switch (offset)
-	{
-		/* offset 0: Motorola datasheet says it isn't used, Hitachi datasheet says it reads as 0s always*/
-		case 0:
-		return 0;
-		/* offset 1 reads the status register: bits 2 1 0 correspond to ints on channels 2,1,0, and bit 7 is an 'OR' of bits 2,1,0 */
-		case 1:
-		logerror("%04X:beezer_sh6840_r - unexpected read, status register is TODO!\n", m_maincpu->pc());
-		return 0;
-		/* offsets 2,4,6 read channel 0,1,2 MSBs and latch the LSB*/
-		case 2: case 4: case 6:
-		m_sh6840_LSB_latch = m_sh6840_timer[((offset>>1)-1)].counter.b.l;
-		return m_sh6840_timer[((offset>>1)-1)].counter.b.h;
-		/* offsets 3,5,7 read the LSB latch*/
-		default: /* case 3,5,7 */
-		return m_sh6840_LSB_latch;
-	}
-}
-
-WRITE8_MEMBER( beezer_sound_device::timer1_w )
-{
-	/* force an update of the stream */
-	m_stream->update();
-	m_sh6840_latchwriteold = m_sh6840_latchwrite;
-	m_sh6840_latchwrite = data&0x80;
-	if ((!m_sh6840_latchwriteold) && (m_sh6840_latchwrite)) // rising edge
-	{
-		m_sh6840_noiselatch1 = (m_sh6840_LFSR&0x1);
-	}
-}
-
-READ8_MEMBER( beezer_sound_device::noise_r )
-{
-	/* force an update of the stream */
-	m_stream->update();
-	return (m_sh6840_LFSR&0x1);
-}
-
-WRITE8_MEMBER( beezer_sound_device::sh6840_w )
-{
-	struct sh6840_timer_channel_beez *sh6840_timer = m_sh6840_timer;
-
-	/* force an update of the stream */
-	m_stream->update();
-
-	switch (offset)
-	{
-		/* offset 0 writes to either channel 0 control or channel 2 control */
-		case 0:
-			if (sh6840_timer[1].cr & 0x01)
-				sh6840_timer[0].cr = data;
-			else
-				sh6840_timer[2].cr = data;
-
-			/* only support mode 0 and 2 */
-			if (((data >> 3) & 5) != 0)
-				fprintf(stderr,"beezer_sh6840_w - channel %d configured for mode %d (write was %02x to offset 0)", (sh6840_timer[1].cr & 0x01) ? 0 : 2, (data >> 3) & 7, data);
-			break;
-
-		/* offset 1 writes to channel 1 control */
-		case 1:
-			sh6840_timer[1].cr = data;
-
-			/* only support mode 0 and 2 */
-			if (((data >> 3) & 5) != 0)
-				fprintf(stderr,"beezer_sh6840_w - channel 1 configured for mode %d (write was %02x to offset 1)", (data >> 3) & 7, data);
-			break;
-
-		/* offsets 2/4/6 write to the common MSB latch */
-		case 2:
-		case 4:
-		case 6:
-			m_sh6840_MSB_latch = data;
-			break;
-
-		/* offsets 3/5/7 write to the LSB controls */
-		case 3:
-		case 5:
-		case 7:
-		{
-			/* latch the timer value */
-			int ch = (offset - 3) / 2;
-			sh6840_timer[ch].timer = (m_sh6840_MSB_latch << 8) | (data & 0xff);
-
-			/* if CR4 is clear, the value is loaded immediately */
-			if (!(sh6840_timer[ch].cr & 0x10))
-				sh6840_timer[ch].counter.w = sh6840_timer[ch].timer;
-			break;
-		}
-	}
-}
-
-
-
-/*************************************
- *
- *  DAC write handler
- *
- *************************************/
-
-WRITE8_MEMBER( beezer_sound_device::sfxctrl_w )
-{
-	m_stream->update();
-	m_sh6840_volume[offset] = data;
-}
-
-//-------------------------------------------------
-//  sound_stream_update - handle a stream update
-//-------------------------------------------------
-
-void beezer_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
-{
-	struct sh6840_timer_channel_beez *sh6840_timer = m_sh6840_timer;
-
-	/* hack to skip the expensive lfsr noise generation unless at least one of the 2 channels which actually depend on it are set to use it as a source */
-	int noisy = ((sh6840_timer[0].cr & sh6840_timer[2].cr & 0x02) == 0);
-	stream_sample_t *buffer = outputs[0];
-
-	/* loop over samples */
-	while (samples--)
-	{
-		struct sh6840_timer_channel_beez *t;
-		int clocks_this_sample;
-		int clocks;
-		int16_t sample1, sample2, sample3, sample0;
-		int16_t sample = 0;
-		sample1 = sample2 = sample3 = sample0 = 0;
-
-		/* determine how many 6840 clocks this sample */
-		m_sh6840_clock_count += m_sh6840_clocks_per_sample;
-		clocks_this_sample = m_sh6840_clock_count >> 24;
-		m_sh6840_clock_count &= (1 << 24) - 1;
-
-		/* skip if nothing enabled */
-		if ((sh6840_timer[0].cr & 0x01) == 0) // if we're not in reset...
-		{
-		// int noise_clocks_this_sample = 0;
-			uint32_t chan1_clocks;
-
-			/* generate noise if configured to do so */
-			if (noisy != 0)
-				sh6840_update_noise(clocks_this_sample);
-
-			/* handle timer 0 if enabled */
-			t = &sh6840_timer[0];
-			clocks = (t->cr & 0x02) ? clocks_this_sample : m_sh6840_noiselatch1;
-			sh6840_apply_clock(t, clocks);
-			sample1 = (t->state && (t->cr & 0x80))?1:0;
-
-			/* handle timer 1 if enabled */
-			t = &sh6840_timer[1];
-			chan1_clocks = t->clocks;
-			clocks = (t->cr & 0x02) ? clocks_this_sample : 0; // TODO: this is WRONG: channel 1 is clocked by a mystery "VCO CLOCK" signal if not set to E clock. it may not even be connected to anything!
-			sh6840_apply_clock(t, clocks);
-			sample2 = (t->state && (t->cr & 0x80))?1:0;
-
-			/* generate channel 1-clocked noise if configured to do so */
-			if (noisy != 0)
-			{
-				sh6840_update_noise(t->clocks - chan1_clocks);
-				if (clocks) m_sh6840_noiselatch3 = (m_sh6840_LFSR&0x1);
-			}
-
-			/* handle timer 2 if enabled */
-			t = &sh6840_timer[2];
-			clocks = (t->cr & 0x02) ? clocks_this_sample : m_sh6840_noiselatch3;
-			/* prescale */
-			if (t->cr & 0x01)
-			{
-				clocks += t->leftovers;
-				t->leftovers = clocks % 8;
-				clocks /= 8;
-			}
-			sh6840_apply_clock(t, clocks);
-			sample3 = (t->state && (t->cr & 0x80))?1:0;
-		}
-		sample0 = m_sh6840_latchwrite?1:0;
-
-		/* stash */
-		/* each sample feeds an xor bit on the sign bit of a sign-magnitude (NOT 2'S COMPLEMENT)
-		 * DAC. This requires some rather convoluted processing:
-		 * samplex*0x80 brings the sample to the sign bit
-		 * m_sh6840_volume[x]&0x80 pulls the sign bit from the dac sample
-		 * m_sh6840_volume[x]&0x7F pulls the magnitude from the dac sample
-		 */
-		sample += (((sample0*0x80)^(m_sh6840_volume[0]&0x80))?-1:1)*(m_sh6840_volume[0]&0x7F);
-		sample += (((sample1*0x80)^(m_sh6840_volume[1]&0x80))?-1:1)*(m_sh6840_volume[1]&0x7F);
-		sample += (((sample2*0x80)^(m_sh6840_volume[2]&0x80))?-1:1)*(m_sh6840_volume[2]&0x7F);
-		sample += (((sample3*0x80)^(m_sh6840_volume[3]&0x80))?-1:1)*(m_sh6840_volume[3]&0x7F);
-		*buffer++ = sample*64; // adding 4 numbers ranging from -128 to 127 yields a range of -512 to 508; to scale that to '-32768 to 32767' we multiply by 64
-	}
-}
diff --git a/src/mame/audio/csd.cpp b/src/mame/audio/csd.cpp
new file mode 100644
index 0000000..47cc6c8
--- /dev/null
+++ b/src/mame/audio/csd.cpp
@@ -0,0 +1,180 @@
+// license: BSD-3-Clause
+// copyright-holders: Aaron Giles
+/***************************************************************************
+
+    Cheap Squeak Deluxe / Artificial Artist Sound Board
+
+***************************************************************************/
+
+#include "csd.h"
+#include "sound/volt_reg.h"
+
+
+//**************************************************************************
+//  DEVICE DEFINITIONS
+//**************************************************************************
+
+extern const device_type MIDWAY_CHEAP_SQUEAK_DELUXE = &device_creator<midway_cheap_squeak_deluxe_device>;
+
+//-------------------------------------------------
+//  audio cpu map
+//-------------------------------------------------
+
+// address map determined by PAL; verified
+static ADDRESS_MAP_START( csdeluxe_map, AS_PROGRAM, 16, midway_cheap_squeak_deluxe_device )
+	ADDRESS_MAP_UNMAP_HIGH
+	ADDRESS_MAP_GLOBAL_MASK(0x1ffff)
+	AM_RANGE(0x00000, 0x07fff) AM_ROM
+	AM_RANGE(0x18000, 0x18007) AM_MIRROR(0x3ff8) AM_DEVREADWRITE8("pia", pia6821_device, read_alt, write_alt, 0xff00) // Spy Hunter accesses the MSB
+	AM_RANGE(0x18000, 0x18007) AM_MIRROR(0x3ff8) AM_DEVREADWRITE8("pia", pia6821_device, read_alt, write_alt, 0x00ff) // Turbo Tag access via the LSB
+	AM_RANGE(0x1c000, 0x1cfff) AM_RAM
+ADDRESS_MAP_END
+
+//-------------------------------------------------
+//  machine configuration
+//-------------------------------------------------
+
+static MACHINE_CONFIG_FRAGMENT(midway_cheap_squeak_deluxe)
+	MCFG_CPU_ADD("cpu", M68000, XTAL_16MHz/2)
+	MCFG_CPU_PROGRAM_MAP(csdeluxe_map)
+
+	MCFG_DEVICE_ADD("pia", PIA6821, 0)
+	MCFG_PIA_WRITEPA_HANDLER(WRITE8(midway_cheap_squeak_deluxe_device, porta_w))
+	MCFG_PIA_WRITEPB_HANDLER(WRITE8(midway_cheap_squeak_deluxe_device, portb_w))
+	MCFG_PIA_IRQA_HANDLER(WRITELINE(midway_cheap_squeak_deluxe_device, irq_w))
+	MCFG_PIA_IRQB_HANDLER(WRITELINE(midway_cheap_squeak_deluxe_device, irq_w))
+
+	MCFG_SOUND_ADD("dac", AD7533, 0) MCFG_SOUND_ROUTE(ALL_OUTPUTS, DEVICE_SELF_OWNER, 1.0)
+	MCFG_DEVICE_ADD("vref", VOLTAGE_REGULATOR, 0) MCFG_VOLTAGE_REGULATOR_OUTPUT(5.0)
+	MCFG_SOUND_ROUTE_EX(0, "dac", 1.0, DAC_VREF_POS_INPUT) MCFG_SOUND_ROUTE_EX(0, "dac", -1.0, DAC_VREF_NEG_INPUT)
+MACHINE_CONFIG_END
+
+machine_config_constructor midway_cheap_squeak_deluxe_device::device_mconfig_additions() const
+{
+	return MACHINE_CONFIG_NAME( midway_cheap_squeak_deluxe );
+}
+
+//-------------------------------------------------
+//  rom_region - device-specific ROM region
+//-------------------------------------------------
+
+ROM_START( csd )
+	ROM_REGION(0x4a, "pal", 0)
+	ROM_LOAD("0304-00803-0052.u15", 0x00, 0x4a, CRC(8b401aee) SHA1(360f3f59877f0bc25b4154782a2011963dd80a52)) // address decoding pal CSD002R0 (PAL14L8)
+ROM_END
+
+const tiny_rom_entry *midway_cheap_squeak_deluxe_device::device_rom_region() const
+{
+	return ROM_NAME( csd );
+}
+
+//-------------------------------------------------
+//  midway_cheap_squeak_deluxe_device - constructor
+//-------------------------------------------------
+
+midway_cheap_squeak_deluxe_device::midway_cheap_squeak_deluxe_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+	device_t(mconfig, MIDWAY_CHEAP_SQUEAK_DELUXE, "Cheap Squeak Deluxe Sound Board", tag, owner, clock, "midcsd", __FILE__),
+	device_mixer_interface(mconfig, *this),
+	m_cpu(*this, "cpu"),
+	m_pia(*this, "pia"),
+	m_dac(*this, "dac"),
+	m_status(0),
+	m_dacval(0)
+{
+}
+
+//-------------------------------------------------
+//  device_start - device-specific startup
+//-------------------------------------------------
+
+void midway_cheap_squeak_deluxe_device::device_start()
+{
+	save_item(NAME(m_status));
+	save_item(NAME(m_dacval));
+}
+
+//-------------------------------------------------
+//  device_timer - timer callbacks
+//-------------------------------------------------
+
+void midway_cheap_squeak_deluxe_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+	m_pia->ca1_w(param);
+
+	// oftentimes games will write one nibble at a time; the sync on this is very
+	// important, so we boost the interleave briefly while this happens
+	machine().scheduler().boost_interleave(attotime::zero, attotime::from_usec(100));
+}
+
+//-------------------------------------------------
+//  stat_r - return the status value
+//-------------------------------------------------
+
+READ8_MEMBER( midway_cheap_squeak_deluxe_device::stat_r )
+{
+	return m_status;
+}
+
+//-------------------------------------------------
+//  sr_w - external 4-bit write to the input latch
+//-------------------------------------------------
+
+WRITE8_MEMBER( midway_cheap_squeak_deluxe_device::sr_w )
+{
+	m_pia->portb_w(data & 0x0f);
+}
+
+//-------------------------------------------------
+//  sirq_w - external irq write
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( midway_cheap_squeak_deluxe_device::sirq_w )
+{
+	synchronize(0, !state);
+}
+
+//-------------------------------------------------
+//  reset_write - write to the reset line
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( midway_cheap_squeak_deluxe_device::reset_w )
+{
+	m_cpu->set_input_line(INPUT_LINE_RESET, state ? ASSERT_LINE : CLEAR_LINE);
+	m_cpu->set_input_line(INPUT_LINE_HALT, state ? ASSERT_LINE : CLEAR_LINE);
+}
+
+//-------------------------------------------------
+//  porta_w - PIA port A writes
+//-------------------------------------------------
+
+WRITE8_MEMBER( midway_cheap_squeak_deluxe_device::porta_w )
+{
+	m_dacval = (data << 2) | (m_dacval & 3);
+	m_dac->write(m_dacval);
+}
+
+//-------------------------------------------------
+//  portb_w - PIA port B writes
+//-------------------------------------------------
+
+WRITE8_MEMBER( midway_cheap_squeak_deluxe_device::portb_w )
+{
+	// bit 4-5, status
+	uint8_t z_mask = m_pia->port_b_z_mask();
+	if (~z_mask & 0x10)  m_status = (m_status & ~1) | ((data >> 4) & 1);
+	if (~z_mask & 0x20)  m_status = (m_status & ~2) | ((data >> 4) & 2);
+
+	// bit 6-7, dac data
+	m_dacval = (m_dacval & ~3) | (data >> 6);
+	m_dac->write(m_dacval);
+}
+
+//-------------------------------------------------
+//  irq_w - IRQ line state changes
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( midway_cheap_squeak_deluxe_device::irq_w )
+{
+	int combined_state = m_pia->irq_a_state() | m_pia->irq_b_state();
+	m_cpu->set_input_line(4, combined_state ? ASSERT_LINE : CLEAR_LINE);
+}
diff --git a/src/mame/audio/csd.h b/src/mame/audio/csd.h
new file mode 100644
index 0000000..a8febae
--- /dev/null
+++ b/src/mame/audio/csd.h
@@ -0,0 +1,64 @@
+// license: BSD-3-Clause
+// copyright-holders: Aaron Giles
+/***************************************************************************
+
+    Cheap Squeak Deluxe / Artificial Artist Sound Board
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef MAME_AUDIO_CSD_H
+#define MAME_AUDIO_CSD_H
+
+#include "emu.h"
+#include "cpu/m68000/m68000.h"
+#include "machine/6821pia.h"
+#include "sound/dac.h"
+
+
+//**************************************************************************
+//  TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> midway_cheap_squeak_deluxe_device
+
+class midway_cheap_squeak_deluxe_device : public device_t, public device_mixer_interface
+{
+public:
+	// construction/destruction
+	midway_cheap_squeak_deluxe_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+	// read/write
+	DECLARE_READ8_MEMBER(stat_r);
+	DECLARE_WRITE8_MEMBER(sr_w);
+	DECLARE_WRITE_LINE_MEMBER(sirq_w);
+	DECLARE_WRITE_LINE_MEMBER(reset_w);
+
+	// internal communications
+	DECLARE_WRITE8_MEMBER(porta_w);
+	DECLARE_WRITE8_MEMBER(portb_w);
+	DECLARE_WRITE_LINE_MEMBER(irq_w);
+
+protected:
+	// device-level overrides
+	virtual machine_config_constructor device_mconfig_additions() const override;
+	virtual const tiny_rom_entry *device_rom_region() const override;
+	virtual void device_start() override;
+	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+
+private:
+	// devices
+	required_device<m68000_device> m_cpu;
+	required_device<pia6821_device> m_pia;
+	required_device<dac_word_interface> m_dac;
+
+	// internal state
+	uint8_t m_status;
+	uint16_t m_dacval;
+};
+
+// device type definition
+extern const device_type MIDWAY_CHEAP_SQUEAK_DELUXE;
+
+#endif // MAME_AUDIO_CSD_H
diff --git a/src/mame/audio/dcs.cpp b/src/mame/audio/dcs.cpp
index 876393c..4e084d8 100644
--- a/src/mame/audio/dcs.cpp
+++ b/src/mame/audio/dcs.cpp
@@ -246,6 +246,7 @@ enum
 
 #define DSIO_DM_PG      ((m_dsio.reg[2] >> 0) & 0x7ff)
 
+#define DSIO_BANK_END   0x7ff
 
 /* these macros are used to reference the DENVER ASIC */
 #define DENV_DSP_SPEED  ((m_dsio.reg[1] >> 2) & 3)    /* read only: 1=33.33MHz */
@@ -256,6 +257,7 @@ enum
 
 #define DENV_DM_PG      ((m_dsio.reg[2] >> 0) & 0x7ff)
 
+#define DENV_BANK_END 0xfff
 
 /*************************************
  *
@@ -384,11 +386,15 @@ ADDRESS_MAP_END
 
 static ADDRESS_MAP_START( dsio_data_map, AS_DATA, 16, dcs_audio_device )
 	ADDRESS_MAP_UNMAP_HIGH
-	AM_RANGE(0x0000, 0x03ff) AM_RAMBANK("databank")
-	AM_RANGE(0x0400, 0x3fdf) AM_RAM
+	AM_RANGE(0x0000, 0x1fff) AM_DEVICE("data_map_bank", address_map_bank_device, amap16)
+	AM_RANGE(0x2000, 0x3fdf) AM_RAM AM_SHARE("dcsint_data")
 	AM_RANGE(0x3fe0, 0x3fff) AM_READWRITE(adsp_control_r, adsp_control_w)
 ADDRESS_MAP_END
 
+static ADDRESS_MAP_START( dsio_rambank_map, AS_PROGRAM, 16, dcs_audio_device )
+	AM_RANGE(0x0000, 0x1fff) AM_RAM
+	AM_RANGE(0x2000, 0x2000 + DSIO_BANK_END) AM_RAMBANK("databank")
+ADDRESS_MAP_END
 
 static ADDRESS_MAP_START( dsio_io_map, AS_IO, 16, dcs_audio_device )
 	ADDRESS_MAP_UNMAP_HIGH
@@ -416,11 +422,16 @@ ADDRESS_MAP_END
 
 static ADDRESS_MAP_START( denver_data_map, AS_DATA, 16, dcs_audio_device )
 	ADDRESS_MAP_UNMAP_HIGH
-	AM_RANGE(0x0000, 0x07ff) AM_RAMBANK("databank")
-	AM_RANGE(0x0800, 0x3fdf) AM_RAM
+	AM_RANGE(0x0000, 0x1fff) AM_DEVICE("data_map_bank", address_map_bank_device, amap16)
+	AM_RANGE(0x2000, 0x3fdf) AM_RAM AM_SHARE("dcsint_data")
 	AM_RANGE(0x3fe0, 0x3fff) AM_READWRITE(adsp_control_r, adsp_control_w)
 ADDRESS_MAP_END
 
+static ADDRESS_MAP_START(denver_rambank_map, AS_PROGRAM, 16, dcs_audio_device)
+	AM_RANGE(0x0000, 0x1fff) AM_RAM
+	AM_RANGE(0x2000, 0x2000 + DENV_BANK_END) AM_RAMBANK("databank")
+ADDRESS_MAP_END
+
 
 static ADDRESS_MAP_START( denver_io_map, AS_IO, 16, dcs_audio_device )
 	ADDRESS_MAP_UNMAP_HIGH
@@ -528,10 +539,18 @@ MACHINE_CONFIG_FRAGMENT( dcs2_audio_dsio )
 	MCFG_CPU_ADD("dsio", ADSP2181, XTAL_32MHz)
 	MCFG_ADSP21XX_SPORT_TX_CB(WRITE32(dcs_audio_device, sound_tx_callback))      /* callback for serial transmit */
 	MCFG_ADSP21XX_TIMER_FIRED_CB(WRITELINE(dcs_audio_device,timer_enable_callback))   /* callback for timer fired */
+	MCFG_ADSP21XX_DMOVLAY_CB(WRITE32(dcs_audio_device, dmovlay_callback)) // callback for adsp 2181 dmovlay instruction
 	MCFG_CPU_PROGRAM_MAP(dsio_program_map)
 	MCFG_CPU_DATA_MAP(dsio_data_map)
 	MCFG_CPU_IO_MAP(dsio_io_map)
 
+	MCFG_DEVICE_ADD("data_map_bank", ADDRESS_MAP_BANK, 0)
+	MCFG_DEVICE_PROGRAM_MAP(dsio_rambank_map)
+	MCFG_ADDRESS_MAP_BANK_ENDIANNESS(ENDIANNESS_LITTLE)
+	MCFG_ADDRESS_MAP_BANK_DATABUS_WIDTH(16)
+	MCFG_ADDRESS_MAP_BANK_ADDRBUS_WIDTH(14)
+	MCFG_ADDRESS_MAP_BANK_STRIDE(0x2000)
+
 	MCFG_TIMER_DEVICE_ADD("dcs_reg_timer", DEVICE_SELF, dcs_audio_device, dcs_irq)
 	MCFG_TIMER_DEVICE_ADD("dcs_int_timer", DEVICE_SELF, dcs_audio_device, internal_timer_callback)
 	MCFG_TIMER_DEVICE_ADD("dcs_sport_timer", DEVICE_SELF, dcs_audio_device, sport0_irq) // roadburn needs this to pass harware test
@@ -562,6 +581,13 @@ MACHINE_CONFIG_FRAGMENT( dcs2_audio_denver )
 	MCFG_CPU_DATA_MAP(denver_data_map)
 	MCFG_CPU_IO_MAP(denver_io_map)
 
+	MCFG_DEVICE_ADD("data_map_bank", ADDRESS_MAP_BANK, 0)
+	MCFG_DEVICE_PROGRAM_MAP(denver_rambank_map)
+	MCFG_ADDRESS_MAP_BANK_ENDIANNESS(ENDIANNESS_LITTLE)
+	MCFG_ADDRESS_MAP_BANK_DATABUS_WIDTH(16)
+	MCFG_ADDRESS_MAP_BANK_ADDRBUS_WIDTH(14)
+	MCFG_ADDRESS_MAP_BANK_STRIDE(0x2000)
+
 	MCFG_TIMER_DEVICE_ADD("dcs_reg_timer", DEVICE_SELF, dcs_audio_device, dcs_irq)
 	MCFG_TIMER_DEVICE_ADD("dcs_int_timer", DEVICE_SELF, dcs_audio_device, internal_timer_callback)
 	MCFG_TIMER_DEVICE_ADD("dcs_sport_timer", DEVICE_SELF, dcs_audio_device, sport0_irq) // Atlantis driver waits for sport0 rx interrupts
@@ -689,8 +715,6 @@ TIMER_CALLBACK_MEMBER( dcs_audio_device::dcs_reset )
 
 		/* rev 4: reset the Denver ASIC */
 		case 4:
-			m_dmovlay_val = 0;
-			dmovlay_remap_memory();
 			denver_reset();
 			break;
 	}
@@ -822,6 +846,7 @@ dcs_audio_device::dcs_audio_device(const machine_config &mconfig, device_type ty
 	m_sounddata_words(0),
 	m_sounddata_banks(0),
 	m_sounddata_bank(0),
+	m_ram_map(*this, "data_map_bank"),
 	m_data_bank(*this, "databank"),
 	m_rom_page(nullptr),
 	m_dram_page(nullptr),
@@ -845,6 +870,7 @@ dcs_audio_device::dcs_audio_device(const machine_config &mconfig, device_type ty
 	m_polling_base(nullptr),
 	m_internal_program_ram(nullptr),
 	m_external_program_ram(nullptr),
+	m_internal_data_ram(nullptr),
 	m_dram_in_mb(0),
 	m_iram(*this, "iram")
 {
@@ -928,6 +954,11 @@ void dcs2_audio_device::device_start()
 	{
 		m_external_program_ram = (uint32_t *)external_ram->ptr();
 	}
+	memory_share *internal_data_ram = memshare("dcsint_data");
+	if (internal_data_ram != nullptr)
+	{
+		m_internal_data_ram = (uint32_t *)internal_ram->ptr();
+	}
 
 	/* find the DCS CPU and the sound ROMs */
 	m_cpu = subdevice<adsp21xx_device>("dcs2");
@@ -937,13 +968,13 @@ void dcs2_audio_device::device_start()
 	{
 		m_cpu = subdevice<adsp21xx_device>("dsio");
 		m_rev = 3;
-		soundbank_words = 0x400;
+		soundbank_words = DSIO_BANK_END + 1;
 	}
 	if (m_cpu == nullptr)
 	{
 		m_cpu = subdevice<adsp21xx_device>("denver");
 		m_rev = 4;
-		soundbank_words = 0x800;
+		soundbank_words = DENV_BANK_END + 1;
 	}
 	if (m_cpu != nullptr && !m_cpu->started())
 		throw device_missing_dependencies();
@@ -965,13 +996,9 @@ void dcs2_audio_device::device_start()
 	/* supports both RAM and ROM variants */
 	if (m_dram_in_mb != 0)
 	{
-		uint32_t ramSize = m_dram_in_mb << (20 - 1);
-		// Add one extra bank for internal ram in ADSP 2181
-		if (m_rev == 4)
-			ramSize += soundbank_words;
-		m_sounddata = auto_alloc_array(machine(), uint16_t, ramSize);
-		save_pointer(NAME(m_sounddata), ramSize);
 		m_sounddata_words = (m_dram_in_mb << 20) / 2;
+		m_sounddata = auto_alloc_array(machine(), uint16_t, m_sounddata_words);
+		save_pointer(NAME(m_sounddata), m_sounddata_words);
 	}
 	else
 	{
@@ -981,7 +1008,9 @@ void dcs2_audio_device::device_start()
 	m_sounddata_banks = m_sounddata_words / soundbank_words;
 	if (m_rev != 2)
 	{
-		m_data_bank->configure_entries(0, m_sounddata_banks, m_sounddata, soundbank_words*2);
+		if (m_ram_map)
+			m_ram_map->set_bank(0);
+		m_data_bank->configure_entries(0, m_sounddata_banks, m_sounddata, soundbank_words * 2);
 	}
 
 
@@ -1303,6 +1332,8 @@ WRITE16_MEMBER( dcs_audio_device::sdrc_w )
 void dcs_audio_device::dsio_reset()
 {
 	memset(&m_dsio, 0, sizeof(m_dsio));
+	m_dmovlay_val = 0;
+	dmovlay_remap_memory();
 }
 
 
@@ -1342,7 +1373,7 @@ WRITE16_MEMBER( dcs_audio_device::dsio_w )
 		/* offset 2 controls RAM pages */
 		case 2:
 			dsio.reg[2] = data;
-			dmovlay_remap_memory();
+			m_data_bank->set_entry(DSIO_DM_PG % m_sounddata_banks);
 			break;
 	}
 }
@@ -1358,6 +1389,8 @@ WRITE16_MEMBER( dcs_audio_device::dsio_w )
 void dcs_audio_device::denver_reset()
 {
 	memset(&m_dsio, 0, sizeof(m_dsio));
+	m_dmovlay_val = 0;
+	dmovlay_remap_memory();
 }
 
 
@@ -1370,6 +1403,7 @@ READ16_MEMBER( dcs_audio_device::denver_r )
 		/* returns 1 for DRAM, 2 for EPROM-based */
 		result = 0x0001;
 	}
+	if (LOG_DCS_IO) logerror("denver: denver_r 0x%x = %04x\n", offset, result);
 	return result;
 }
 
@@ -1417,6 +1451,7 @@ WRITE16_MEMBER( dcs_audio_device::denver_w )
 				m_fifo_reset_w(1);
 			break;
 	}
+	if (LOG_DCS_IO) logerror("denver: denver_w 0x%x = %04x\n", offset, data);
 }
 
 
@@ -1477,11 +1512,9 @@ void dcs_audio_device::dmovlay_remap_memory()
 	// Internal ram is bank 0
 	int bankSel;
 	if (m_dmovlay_val == 0) {
-		bankSel = 0;
-		m_data_bank->set_entry(bankSel);
+		m_ram_map->set_bank(0);
 	} else {
-		bankSel = 1 + (DSIO_DM_PG % m_sounddata_banks);
-		m_data_bank->set_entry(bankSel);
+		m_ram_map->set_bank(1);
 	}
 	if (LOG_DCS_IO)
 		logerror("%s dmovlay_remap_memory: Switching data ram location bankSel = %i\n", machine().describe_context(), bankSel);
diff --git a/src/mame/audio/dcs.h b/src/mame/audio/dcs.h
index 11645ec..e041512 100644
--- a/src/mame/audio/dcs.h
+++ b/src/mame/audio/dcs.h
@@ -11,6 +11,7 @@
 
 #include "cpu/adsp2100/adsp2100.h"
 #include "sound/dmadac.h"
+#include "machine/bankdev.h"
 
 #define MCFG_DCS2_AUDIO_DRAM_IN_MB(_dram_in_mb) \
 	dcs_audio_device::static_set_dram_in_mb(*device, _dram_in_mb);
@@ -167,6 +168,7 @@ protected:
 	uint32_t      m_sounddata_banks;
 	uint16_t      m_sounddata_bank;
 
+	optional_device<address_map_bank_device> m_ram_map;
 	optional_memory_bank    m_data_bank;
 	memory_bank *           m_rom_page;
 	memory_bank *           m_dram_page;
@@ -203,6 +205,7 @@ protected:
 	uint16_t *m_polling_base;
 	uint32_t *m_internal_program_ram;
 	uint32_t *m_external_program_ram;
+	uint32_t *m_internal_data_ram;
 
 	int m_dmovlay_val;
 
diff --git a/src/mame/audio/gorf.cpp b/src/mame/audio/gorf.cpp
deleted file mode 100644
index 21f7272..0000000
--- a/src/mame/audio/gorf.cpp
+++ /dev/null
@@ -1,190 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Mike Coates
-/**************************************************************************
-
-    Gorf/Votrax SC-01 Emulator
-
-    Mike at Dissfulfils.co.uk
-
-        Modified to match phonemes to words
-
-        Ajudd at quantime.co.uk
-
-**************************************************************************
-
-gorf_sh_w      - Write data to votrax port
-gorf_sh_status - Return busy status (-1 = busy)
-gorf_port_2_r  - Returns status of voice port
-gorf_sh_ update- Null
-
-**************************************************************************/
-
-#include "emu.h"
-#include "cpu/z80/z80.h"
-#include "includes/astrocde.h"
-#include "audio/gorf.h"
-
-
-/****************************************************************************
- * 64 Phonemes - currently 1 sample per phoneme, will be combined sometime!
- ****************************************************************************/
-
-static const char *const PhonemeTable[65] =
-{
-	"EH3","EH2","EH1","PA0","DT" ,"A1" ,"A2" ,"ZH",
-	"AH2","I3" ,"I2" ,"I1" ,"M"  ,"N"  ,"B"  ,"V",
-	"CH" ,"SH" ,"Z"  ,"AW1","NG" ,"AH1","OO1","OO",
-	"L"  ,"K"  ,"J"  ,"H"  ,"G"  ,"F"  ,"D"  ,"S",
-	"A"  ,"AY" ,"Y1" ,"UH3","AH" ,"P"  ,"O"  ,"I",
-	"U"  ,"Y"  ,"T"  ,"R"  ,"E"  ,"W"  ,"AE" ,"AE1",
-	"AW2","UH2","UH1","UH" ,"O2" ,"O1" ,"IU" ,"U1",
-	"THV","TH" ,"ER" ,"EH" ,"E1" ,"AW" ,"PA1","STOP",
-	nullptr
-};
-
-static const char *const GorfWordTable[] =
-{
-	"A2AYY1","A2E1","UH1GEH1I3N","AE1EH2M","AEM",
-	"AE1EH3ND","UH1NAH2I1YLA2SHUH2N","AH2NUHTHER","AH1NUHTHVRR",
-	"AH1R","UHR","UH1VEH1EH3NNDJER","BAEEH3D","BAEEH1D","BE",
-	"BEH3EH1N","buht","BUH1DTTEH2NN","KUHDEH2T",
-	"KAE1NUH1T","KAE1EH3PTI3N",
-	"KRAH2UH3NI3KUH3O2LZ","KO1UH3I3E1N","KO1UH3I3E1NS",
-	"KERNAH2L","KAH1NCHEHSNEHS","DE1FEH1NDER",
-	"DE1STRO1I1Y","DE1STRO1I1Y1D",
-	"DU1UM","DRAW1S","EHMPAH2I3YR","EHND",
-	"EH1NEH1MY","EH1SKA1E1P","FLEHGSHIP",
-	"FOR","GUH1LAEKTI1K",
-	"DJEH2NERUH3L","GDTO1O1RRFF","GDTO1RFYA2N","GDTO1RFE1EH2N","GDTO1RFYA2NS",
-	"HAH1HAH1HAH1HAH1","hahaher.wav","HUHRDER",
-	"HAE1EH3V","HI1TI1NG","AH1I1Y", "AH1I1Y1","I1MPAH1SI1BL",
-	"IN*","INSERT","I1S","LI1V","LAWNG","MEE1T","MUU1V",
-	"MAH2I1Y","MAH2I3Y","NIR","NEHKST","NUH3AH2YS","NO",
-	"NAH1O1U1W","PA1","PLA1AYER","PRE1PAE1ER","PRI1SI3NEH3RS",
-	"PRUH2MOTEH3D","POO1IUSH","RO1U1BAH1T","RO1U1BAH1TS",
-	"RO1U1BAH1UH3TS","SEK", "SHIP","SHAH1UH3T","SUHM","SPA2I3YS","PA0",
-	"SERVAH2I1Y1VUH3L","TAK","THVUH","THVUH1",
-	"THUH","TAH1EH3YM","TU","TIUU1",
-	"UH2NBE1AYTUH3BUH3L",
-	"WORAYY1EH3R","WORAYY1EH3RS","WI1L",
-	"Y1I3U1","YIUU1U1","YI1U1U1","Y1IUU1U1","Y1I1U1U1","YOR","YU1O1RSEH1LF","s.wav",
-	"FO1R","FO2R","WIL","GDTO1RVYA2N",
-
-	"KO1UH3I3AYNN",
-	"UH1TAEEH3K","BAH2I3Y1T","KAH1NKER","DYVAH1U1ER","DUHST","GAE1LUH1KSY","GAH1EH3T",
-	"PAH1I1R","TRAH2I1Y","SU1PRE1N","AWL","HA2AYL",
-	"EH1MPAH1I1R",
-nullptr
-};
-
-#define num_samples (sizeof(GorfWordTable)/sizeof(char *))
-
-const char *const gorf_sample_names[] =
-{
-	"*gorf","a","a","again","am","am","and","anhilatn",
-	"another","another","are","are",
-	"avenger","bad","bad","be",
-	"been","but","button","cadet",
-	"cannot","captain","chronicl","coin","coins","colonel",
-	"consciou","defender","destroy","destroyd",
-	"doom","draws","empire","end",
-	"enemy","escape","flagship","for","galactic",
-	"general","gorf","gorphian","gorphian","gorphins",
-	"hahahahu","hahaher","harder","have",
-	"hitting","i","i","impossib","in","insert",
-	"is","live","long","meet","move",
-	"my","my",
-	"near","next","nice","no",
-	"now","pause","player","prepare","prisonrs",
-	"promoted","push","robot","robots","robots",
-	"seek","ship","shot","some","space","spause",
-	"survival","take","the","the","the","time",
-	"to","to","unbeatab",
-	"warrior","warriors","will",
-	"you","you","you","you","your","your","yourself",
-	"s","for","for","will","gorph",
-// Missing Samples
-	"coin", "attack","bite","conquer","devour","dust",
-	"galaxy","got","power","try","supreme","all",
-	"hail","emperor",
-	nullptr
-};
-
-
-READ8_MEMBER( astrocde_state::gorf_speech_r )
-{
-	uint8_t data = offset >> 8;
-#if USE_FAKE_VOTRAX
-		int Phoneme, Intonation;
-	int i = 0;
-	offset &= 0xff;
-
-	m_totalword_ptr = m_totalword;
-
-	Phoneme = data & 0x3F;
-	Intonation = data >> 6;
-
-	logerror("Date : %d Speech : %s at intonation %d\n",Phoneme, PhonemeTable[Phoneme],Intonation);
-
-	if(Phoneme==63) {
-		m_samples->stop(0);
-		if (strlen(m_totalword)>2) logerror("Clearing sample %s\n",m_totalword);
-		m_totalword[0] = 0;                 /* Clear the total word stack */
-		return data;
-	}
-
-	/* Phoneme to word translation */
-
-	if (*(m_totalword) == 0) {
-		strcpy(m_totalword,PhonemeTable[Phoneme]);                      /* Copy over the first phoneme */
-		if (m_plural != 0) {
-			logerror("found a possible plural at %d\n",m_plural-1);
-			if (!strcmp("S",m_totalword)) {         /* Plural check */
-				m_samples->start(0, num_samples-2);      /* play the sample at position of word */
-				m_samples->set_frequency(0, 11025);    /* play at correct rate */
-				m_totalword[0] = 0;                 /* Clear the total word stack */
-				m_oldword[0] = 0;                   /* Clear the total word stack */
-				return data;
-			} else {
-				m_plural=0;
-			}
-		}
-	} else
-		strcat(m_totalword,PhonemeTable[Phoneme]);                      /* Copy over the first phoneme */
-
-	logerror("Total word = %s\n",m_totalword);
-
-	for (i=0; GorfWordTable[i]; i++) {
-		if (!strcmp(GorfWordTable[i],m_totalword)) {        /* Scan the word (sample) table for the complete word */
-			if ((!strcmp("GDTO1RFYA2N",m_totalword)) || (!strcmp("RO1U1BAH1T",m_totalword)) || (!strcmp("KO1UH3I3E1N",m_totalword)) || (!strcmp("WORAYY1EH3R",m_totalword)) || (!strcmp("IN",m_totalword)) ) {              /* May be m_plural */
-				m_plural=i+1;
-				strcpy(m_oldword,m_totalword);
-				logerror("Storing sample position %d and copying string %s\n",m_plural,m_oldword);
-			} else {
-				m_plural=0;
-			}
-			m_samples->start(0, i);                      /* play the sample at position of word */
-			m_samples->set_frequency(0, 11025);       /* play at correct rate */
-			logerror("Playing sample %d",i);
-			m_totalword[0] = 0;                 /* Clear the total word stack */
-			return data;
-		}
-	}
-#else
-	m_votrax->inflection_w(space, 0, data >> 6);
-	m_votrax->write(space, 0, data);
-#endif
-
-	/* Note : We should really also use volume in this as well as frequency */
-	return data;                                   /* Return nicely */
-}
-
-
-CUSTOM_INPUT_MEMBER( astrocde_state::gorf_speech_status_r )
-{
-#if USE_FAKE_VOTRAX
-	return !m_samples->playing(0);
-#else
-	return m_votrax->request();
-#endif
-}
diff --git a/src/mame/audio/gorf.h b/src/mame/audio/gorf.h
deleted file mode 100644
index 0d14337..0000000
--- a/src/mame/audio/gorf.h
+++ /dev/null
@@ -1,4 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Mike Coates
-
-extern const char *const gorf_sample_names[];
diff --git a/src/mame/audio/gottlieb.cpp b/src/mame/audio/gottlieb.cpp
index 5a7924a..75308e7 100644
--- a/src/mame/audio/gottlieb.cpp
+++ b/src/mame/audio/gottlieb.cpp
@@ -30,225 +30,6 @@ extern const device_type GOTTLIEB_SOUND_REV1_WITH_VOTRAX = &device_creator<gottl
 extern const device_type GOTTLIEB_SOUND_REV2 = &device_creator<gottlieb_sound_r2_device>;
 
 
-
-//**************************************************************************
-//  OLD CRAPPY SAMPLE PLAYER
-//**************************************************************************
-
-#if USE_FAKE_VOTRAX
-
-void gottlieb_sound_r1_device::trigger_sample(uint8_t data)
-{
-	/* Reactor samples */
-	if (strcmp(machine().system().name, "reactor") == 0)
-	{
-		switch (data)
-		{
-			case 55:
-			case 56:
-			case 57:
-			case 59:
-				m_samples->start(0, data - 53);
-				break;
-
-			case 31:
-				m_score_sample = 7;
-				break;
-
-			case 39:
-				m_score_sample++;
-				if (m_score_sample < 20)
-					m_samples->start(0, m_score_sample);
-				break;
-		}
-	}
-
-	/* Q*Bert samples */
-	else
-	{
-		switch (data)
-		{
-			case 17:
-			case 18:
-			case 19:
-			case 20:
-			case 21:
-				m_samples->start(0, (data - 17) * 8 + m_random_offset);
-				m_random_offset = (m_random_offset + 1) & 7;
-				break;
-
-			case 22:
-				m_samples->start(0,40);
-				break;
-
-			case 23:
-				m_samples->start(0,41);
-				break;
-		}
-	}
-}
-
-void gottlieb_sound_r1_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
-{
-	m_audiocpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE);
-}
-
-void gottlieb_sound_r1_device::fake_votrax_data_w(uint8_t data)
-{
-	static const char *const PhonemeTable[0x40] =
-	{
-		"EH3", "EH2", "EH1", "PA0", "DT" , "A1" , "A2" , "ZH",
-		"AH2", "I3" , "I2" , "I1" , "M"  , "N"  , "B"  , "V",
-		"CH" , "SH" , "Z"  , "AW1", "NG" , "AH1", "OO1", "OO",
-		"L"  , "K"  , "J"  , "H"  , "G"  , "F"  , "D"  , "S",
-		"A"  , "AY" , "Y1" , "UH3", "AH" , "P"  , "O"  , "I",
-		"U"  , "Y"  , "T"  , "R"  , "E"  , "W"  , "AE" , "AE1",
-		"AW2", "UH2", "UH1", "UH" , "O2" , "O1" , "IU" , "U1",
-		"THV", "TH" , "ER" , "EH" , "E1" , "AW" , "PA1", "STOP"
-	};
-
-	data ^= 0xff;
-
-logerror("Votrax: intonation %d, phoneme %02x %s\n",data >> 6,data & 0x3f,PhonemeTable[data & 0x3f]);
-
-	m_votrax_queue[m_votrax_queuepos++] = data;
-
-	if ((data & 0x3f) == 0x3f)
-	{
-		if (m_votrax_queuepos > 1)
-		{
-			int last = -1;
-			int i;
-			char phonemes[200];
-
-			phonemes[0] = 0;
-			for (i = 0;i < m_votrax_queuepos-1;i++)
-			{
-				static const char *const inf[4] = { "[0]", "[1]", "[2]", "[3]" };
-				int phoneme = m_votrax_queue[i] & 0x3f;
-				int inflection = m_votrax_queue[i] >> 6;
-				if (inflection != last) strcat(phonemes, inf[inflection]);
-				last = inflection;
-				if (phoneme == 0x03 || phoneme == 0x3e) strcat(phonemes," ");
-				else strcat(phonemes,PhonemeTable[phoneme]);
-			}
-
-			osd_printf_debug("Votrax played '%s'\n", phonemes);
-
-			if (strcmp(phonemes, "[0] HEH3LOOW     AH1EH3I3YMTERI2NDAHN") == 0)   /* Q-Bert & Tylz - Hello, I am turned on */
-								m_samples->start(0, 42);
-			else if (strcmp(phonemes, "[0]BAH1EH1Y") == 0)                            /* Q-Bert - Bye, bye */
-				m_samples->start(0, 43);
-			else if (strcmp(phonemes, "[0]A2YHT LEH2FTTH") == 0)                      /* Reactor - Eight left */
-				m_samples->start(0, 0);
-			else if (strcmp(phonemes, "[0]SI3KS DTYN LEH2FTTH") == 0)                 /* Reactor - Sixteen left */
-				m_samples->start(0, 1);
-			else if (strcmp(phonemes, "[0]WO2RNYNG KO2R UH1NSDTABUH1L") == 0)         /* Reactor - Warning core unstable */
-				m_samples->start(0, 5);
-			else if (strcmp(phonemes, "[0]CHAMBERR   AE1EH2KTI1VA1I3DTEH1DT ") == 0) /* Reactor - Chamber activated */
-				m_samples->start(0, 7);
-		}
-
-		m_votrax_queuepos = 0;
-	}
-
-	/* generate a NMI after a while to make the CPU continue to send data */
-	timer_set(attotime::from_usec(50));
-}
-
-static const char *const reactor_sample_names[] =
-{
-	"*reactor",
-	"fx_53", /* "8 left" */
-	"fx_54", /* "16 left" */
-	"fx_55", /* "24 left" */
-	"fx_56", /* "32 left" */
-	"fx_57", /* "40 left" */
-	"fx_58", /* "warning, core unstable" */
-	"fx_59", /* "bonus" */
-	"fx_31", /* "chamber activated" */
-	"fx_39a", /* "2000" */
-	"fx_39b", /* "5000" */
-	"fx_39c", /* "10000" */
-	"fx_39d", /* "15000" */
-	"fx_39e", /* "20000" */
-	"fx_39f", /* "25000" */
-	"fx_39g", /* "30000" */
-	"fx_39h", /* "35000" */
-	"fx_39i", /* "40000" */
-	"fx_39j", /* "45000" */
-	"fx_39k", /* "50000" */
-	"fx_39l", /* "55000" */
-	nullptr   /* end of array */
-};
-
-static const char *const qbert_sample_names[] =
-{
-	"*qbert",
-	"fx_17a", /* random speech, voice clock 255 */
-	"fx_17b", /* random speech, voice clock 255 */
-	"fx_17c", /* random speech, voice clock 255 */
-	"fx_17d", /* random speech, voice clock 255 */
-	"fx_17e", /* random speech, voice clock 255 */
-	"fx_17f", /* random speech, voice clock 255 */
-	"fx_17g", /* random speech, voice clock 255 */
-	"fx_17h", /* random speech, voice clock 255 */
-	"fx_18a", /* random speech, voice clock 176 */
-	"fx_18b", /* random speech, voice clock 176 */
-	"fx_18c", /* random speech, voice clock 176 */
-	"fx_18d", /* random speech, voice clock 176 */
-	"fx_18e", /* random speech, voice clock 176 */
-	"fx_18f", /* random speech, voice clock 176 */
-	"fx_18g", /* random speech, voice clock 176 */
-	"fx_18h", /* random speech, voice clock 176 */
-	"fx_19a", /* random speech, voice clock 128 */
-	"fx_19b", /* random speech, voice clock 128 */
-	"fx_19c", /* random speech, voice clock 128 */
-	"fx_19d", /* random speech, voice clock 128 */
-	"fx_19e", /* random speech, voice clock 128 */
-	"fx_19f", /* random speech, voice clock 128 */
-	"fx_19g", /* random speech, voice clock 128 */
-	"fx_19h", /* random speech, voice clock 128 */
-	"fx_20a", /* random speech, voice clock 96 */
-	"fx_20b", /* random speech, voice clock 96 */
-	"fx_20c", /* random speech, voice clock 96 */
-	"fx_20d", /* random speech, voice clock 96 */
-	"fx_20e", /* random speech, voice clock 96 */
-	"fx_20f", /* random speech, voice clock 96 */
-	"fx_20g", /* random speech, voice clock 96 */
-	"fx_20h", /* random speech, voice clock 96 */
-	"fx_21a", /* random speech, voice clock 62 */
-	"fx_21b", /* random speech, voice clock 62 */
-	"fx_21c", /* random speech, voice clock 62 */
-	"fx_21d", /* random speech, voice clock 62 */
-	"fx_21e", /* random speech, voice clock 62 */
-	"fx_21f", /* random speech, voice clock 62 */
-	"fx_21g", /* random speech, voice clock 62 */
-	"fx_21h", /* random speech, voice clock 62 */
-	"fx_22", /* EH2 with decreasing voice clock */
-	"fx_23", /* O1 with varying voice clock */
-	"fx_28",
-	"fx_36",
-	nullptr   /* end of array */
-};
-
-MACHINE_CONFIG_FRAGMENT( reactor_samples )
-	MCFG_SOUND_ADD("samples", SAMPLES, 0)
-	MCFG_SAMPLES_CHANNELS(1)
-	MCFG_SAMPLES_NAMES(reactor_sample_names)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "speaker", 1.0)
-MACHINE_CONFIG_END
-
-MACHINE_CONFIG_FRAGMENT( qbert_samples )
-	MCFG_SOUND_ADD("samples", SAMPLES, 0)
-	MCFG_SAMPLES_CHANNELS(1)
-	MCFG_SAMPLES_NAMES(qbert_sample_names)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "speaker", 1.0)
-MACHINE_CONFIG_END
-
-#endif
-
-
 //**************************************************************************
 //  REV 0 SOUND BOARD: 6502 + 6530 + DAC
 //**************************************************************************
@@ -390,12 +171,6 @@ gottlieb_sound_r1_device::gottlieb_sound_r1_device(const machine_config &mconfig
 		m_votrax(*this, "votrax"),
 		//m_populate_votrax(false),
 		m_last_speech_clock(0)
-#if USE_FAKE_VOTRAX
-		, m_samples(*this, ":samples"),
-		m_score_sample(0),
-		m_random_offset(0),
-		m_votrax_queuepos(0)
-#endif
 {
 }
 
@@ -407,12 +182,6 @@ gottlieb_sound_r1_device::gottlieb_sound_r1_device(const machine_config &mconfig
 		m_votrax(*this, "votrax"),
 		//m_populate_votrax(populate_votrax),
 		m_last_speech_clock(0)
-#if USE_FAKE_VOTRAX
-		, m_samples(*this, ":samples"),
-		m_score_sample(0),
-		m_random_offset(0),
-		m_votrax_queuepos(0)
-#endif
 {
 }
 
@@ -427,11 +196,6 @@ WRITE8_MEMBER( gottlieb_sound_r1_device::write )
 	uint8_t pa7 = (data & 0x0f) != 0xf;
 	uint8_t pa0_5 = ~data & 0x3f;
 	m_riot->porta_in_set(pa0_5 | (pa7 << 7), 0xbf);
-
-#if USE_FAKE_VOTRAX
-	if (pa7 && m_samples != nullptr)
-		trigger_sample(pa0_5);
-#endif
 }
 
 
@@ -469,10 +233,6 @@ WRITE8_MEMBER( gottlieb_sound_r1_device::votrax_data_w )
 		m_votrax->inflection_w(space, offset, data >> 6);
 		m_votrax->write(space, offset, ~data & 0x3f);
 	}
-
-#if USE_FAKE_VOTRAX
-	fake_votrax_data_w(data);
-#endif
 }
 
 
diff --git a/src/mame/audio/gottlieb.h b/src/mame/audio/gottlieb.h
index 77753f5..b32b70c 100644
--- a/src/mame/audio/gottlieb.h
+++ b/src/mame/audio/gottlieb.h
@@ -15,11 +15,6 @@
 #include "sound/votrax.h"
 
 
-// set to 0 to enable Votrax device and disable samples
-#define USE_FAKE_VOTRAX         (1)
-
-
-
 //**************************************************************************
 //  GLOBAL VARIABLES
 //**************************************************************************
@@ -108,19 +103,6 @@ private:
 	// internal state
 	//bool            m_populate_votrax;
 	uint8_t           m_last_speech_clock;
-
-#if USE_FAKE_VOTRAX
-protected:
-	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
-private:
-	void fake_votrax_data_w(uint8_t data);
-	void trigger_sample(uint8_t data);
-	optional_device<samples_device> m_samples;
-	uint8_t m_score_sample;
-	uint8_t m_random_offset;
-	uint8_t m_votrax_queue[100];
-	uint8_t m_votrax_queuepos;
-#endif
 };
 
 // fully populated rev 1 sound board
@@ -203,10 +185,3 @@ private:
 	uint8_t       m_sp0250_latch;
 };
 
-
-/*----------- defined in audio/gottlieb.c -----------*/
-
-#if USE_FAKE_VOTRAX
-MACHINE_CONFIG_EXTERN( reactor_samples );
-MACHINE_CONFIG_EXTERN( qbert_samples );
-#endif
diff --git a/src/mame/audio/midway.cpp b/src/mame/audio/midway.cpp
index f6f7268..27dc8fe 100644
--- a/src/mame/audio/midway.cpp
+++ b/src/mame/audio/midway.cpp
@@ -21,7 +21,6 @@
 //**************************************************************************
 
 #define SSIO_CLOCK          XTAL_16MHz
-#define CSDELUXE_CLOCK      XTAL_16MHz
 #define SOUNDSGOOD_CLOCK    XTAL_16MHz
 #define TURBOCS_CLOCK       XTAL_8MHz
 #define SQUAWKTALK_CLOCK    XTAL_3_579545MHz
@@ -33,7 +32,6 @@
 //**************************************************************************
 
 extern const device_type MIDWAY_SSIO = &device_creator<midway_ssio_device>;
-extern const device_type MIDWAY_CHIP_SQUEAK_DELUXE = &device_creator<midway_chip_squeak_deluxe_device>;
 extern const device_type MIDWAY_SOUNDS_GOOD = &device_creator<midway_sounds_good_device>;
 extern const device_type MIDWAY_TURBO_CHIP_SQUEAK = &device_creator<midway_turbo_chip_squeak_device>;
 extern const device_type MIDWAY_SQUAWK_N_TALK = &device_creator<midway_squawk_n_talk_device>;
@@ -484,205 +482,6 @@ void midway_ssio_device::device_timer(emu_timer &timer, device_timer_id id, int
 
 
 //**************************************************************************
-//  CHIP SQUEAK DELUXE BOARD
-//**************************************************************************
-
-//-------------------------------------------------
-//  midway_chip_squeak_deluxe_device - constructor
-//-------------------------------------------------
-
-midway_chip_squeak_deluxe_device::midway_chip_squeak_deluxe_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
-	: device_t(mconfig, MIDWAY_CHIP_SQUEAK_DELUXE, "Midway Chip Squeak Deluxe Sound Board", tag, owner, clock, "midcsd", __FILE__),
-		device_mixer_interface(mconfig, *this),
-		m_cpu(*this, "cpu"),
-		m_pia(*this, "pia"),
-		m_dac(*this, "dac"),
-		m_status(0),
-		m_dacval(0)
-{
-}
-
-
-//-------------------------------------------------
-//  read - return the status value
-//-------------------------------------------------
-
-READ8_MEMBER(midway_chip_squeak_deluxe_device::read)
-{
-	return m_status;
-}
-
-
-//-------------------------------------------------
-//  write - handle an external write to the input
-//  latch
-//-------------------------------------------------
-
-WRITE8_MEMBER(midway_chip_squeak_deluxe_device::write)
-{
-	synchronize(0, data);
-}
-
-
-//-------------------------------------------------
-//  reset_write - write to the reset line
-//-------------------------------------------------
-
-WRITE_LINE_MEMBER(midway_chip_squeak_deluxe_device::reset_write)
-{
-	m_cpu->set_input_line(INPUT_LINE_RESET, state ? ASSERT_LINE : CLEAR_LINE);
-}
-
-
-//-------------------------------------------------
-//  porta_w - PIA port A writes
-//-------------------------------------------------
-
-WRITE8_MEMBER(midway_chip_squeak_deluxe_device::porta_w)
-{
-	m_dacval = (data << 2) | (m_dacval & 3);
-	m_dac->write(m_dacval);
-}
-
-
-//-------------------------------------------------
-//  portb_w - PIA port B writes
-//-------------------------------------------------
-
-WRITE8_MEMBER(midway_chip_squeak_deluxe_device::portb_w)
-{
-	m_dacval = (m_dacval & ~3) | (data >> 6);
-	m_dac->write(m_dacval);
-
-	uint8_t z_mask = m_pia->port_b_z_mask();
-	if (~z_mask & 0x10)  m_status = (m_status & ~1) | ((data >> 4) & 1);
-	if (~z_mask & 0x20)  m_status = (m_status & ~2) | ((data >> 4) & 2);
-}
-
-
-//-------------------------------------------------
-//  irq_w - IRQ line state changes
-//-------------------------------------------------
-
-WRITE_LINE_MEMBER(midway_chip_squeak_deluxe_device::irq_w)
-{
-	int combined_state = m_pia->irq_a_state() | m_pia->irq_b_state();
-	m_cpu->set_input_line(4, combined_state ? ASSERT_LINE : CLEAR_LINE);
-}
-
-
-//-------------------------------------------------
-//  pia_r - PIA read access
-//-------------------------------------------------
-
-READ16_MEMBER(midway_chip_squeak_deluxe_device::pia_r)
-{
-	// Spy Hunter accesses the MSB; Turbo Tag access via the LSB
-	// My guess is that Turbo Tag works through a fluke, whereby the 68000
-	// using the MOVEP instruction outputs the same value on the high and
-	// low bytes.
-	if (ACCESSING_BITS_8_15)
-		return m_pia->read_alt(space, offset) << 8;
-	else
-		return m_pia->read_alt(space, offset);
-}
-
-
-//-------------------------------------------------
-//  pia_w - PIA write access
-//-------------------------------------------------
-
-WRITE16_MEMBER(midway_chip_squeak_deluxe_device::pia_w)
-{
-	if (ACCESSING_BITS_8_15)
-		m_pia->write_alt(space, offset, data >> 8);
-	else
-		m_pia->write_alt(space, offset, data);
-}
-
-
-//-------------------------------------------------
-//  audio CPU map
-//-------------------------------------------------
-
-// address map determined by PAL; not verified
-static ADDRESS_MAP_START( csdeluxe_map, AS_PROGRAM, 16, midway_chip_squeak_deluxe_device )
-	ADDRESS_MAP_UNMAP_HIGH
-	ADDRESS_MAP_GLOBAL_MASK(0x1ffff)
-	AM_RANGE(0x000000, 0x007fff) AM_ROM
-	AM_RANGE(0x018000, 0x018007) AM_READWRITE(pia_r, pia_w)
-	AM_RANGE(0x01c000, 0x01cfff) AM_RAM
-ADDRESS_MAP_END
-
-
-//-------------------------------------------------
-//  machine configuration
-//-------------------------------------------------
-
-static MACHINE_CONFIG_FRAGMENT(midway_chip_squeak_deluxe)
-	MCFG_CPU_ADD("cpu", M68000, CSDELUXE_CLOCK/2)
-	MCFG_CPU_PROGRAM_MAP(csdeluxe_map)
-
-	MCFG_DEVICE_ADD("pia", PIA6821, 0)
-	MCFG_PIA_WRITEPA_HANDLER(WRITE8(midway_chip_squeak_deluxe_device, porta_w))
-	MCFG_PIA_WRITEPB_HANDLER(WRITE8(midway_chip_squeak_deluxe_device, portb_w))
-	MCFG_PIA_IRQA_HANDLER(WRITELINE(midway_chip_squeak_deluxe_device, irq_w))
-	MCFG_PIA_IRQB_HANDLER(WRITELINE(midway_chip_squeak_deluxe_device, irq_w))
-
-	MCFG_SOUND_ADD("dac", DAC_10BIT_R2R, 0) MCFG_SOUND_ROUTE(ALL_OUTPUTS, DEVICE_SELF_OWNER, 1.0) // unknown DAC
-	MCFG_DEVICE_ADD("vref", VOLTAGE_REGULATOR, 0) MCFG_VOLTAGE_REGULATOR_OUTPUT(5.0)
-	MCFG_SOUND_ROUTE_EX(0, "dac", 1.0, DAC_VREF_POS_INPUT) MCFG_SOUND_ROUTE_EX(0, "dac", -1.0, DAC_VREF_NEG_INPUT)
-MACHINE_CONFIG_END
-
-
-//-------------------------------------------------
-//  device_mconfig_additions - return a pointer to
-//  the device's machine fragment
-//-------------------------------------------------
-
-machine_config_constructor midway_chip_squeak_deluxe_device::device_mconfig_additions() const
-{
-	return MACHINE_CONFIG_NAME( midway_chip_squeak_deluxe );
-}
-
-
-//-------------------------------------------------
-//  device_start - device-specific startup
-//-------------------------------------------------
-
-void midway_chip_squeak_deluxe_device::device_start()
-{
-	save_item(NAME(m_status));
-	save_item(NAME(m_dacval));
-}
-
-
-//-------------------------------------------------
-//  device_reset - device-specific reset
-//-------------------------------------------------
-
-void midway_chip_squeak_deluxe_device::device_reset()
-{
-}
-
-
-//-------------------------------------------------
-//  device_timer - timer callbacks
-//-------------------------------------------------
-
-void midway_chip_squeak_deluxe_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
-{
-	m_pia->portb_w(param & 0x0f);
-	m_pia->ca1_w(~param & 0x10);
-
-	// oftentimes games will write one nibble at a time; the sync on this is very
-	// important, so we boost the interleave briefly while this happens
-	machine().scheduler().boost_interleave(attotime::zero, attotime::from_usec(100));
-}
-
-
-
-//**************************************************************************
 //  SOUNDS GOOD BOARD
 //**************************************************************************
 
@@ -965,7 +764,7 @@ static MACHINE_CONFIG_FRAGMENT(midway_turbo_chip_squeak)
 	MCFG_PIA_IRQA_HANDLER(WRITELINE(midway_turbo_chip_squeak_device, irq_w))
 	MCFG_PIA_IRQB_HANDLER(WRITELINE(midway_turbo_chip_squeak_device, irq_w))
 
-	MCFG_SOUND_ADD("dac", DAC_10BIT_R2R, 0) MCFG_SOUND_ROUTE(ALL_OUTPUTS, DEVICE_SELF_OWNER, 1.0) // unknown DAC
+	MCFG_SOUND_ADD("dac", AD7533, 0) MCFG_SOUND_ROUTE(ALL_OUTPUTS, DEVICE_SELF_OWNER, 1.0)
 	MCFG_DEVICE_ADD("vref", VOLTAGE_REGULATOR, 0) MCFG_VOLTAGE_REGULATOR_OUTPUT(5.0)
 	MCFG_SOUND_ROUTE_EX(0, "dac", 1.0, DAC_VREF_POS_INPUT) MCFG_SOUND_ROUTE_EX(0, "dac", -1.0, DAC_VREF_NEG_INPUT)
 MACHINE_CONFIG_END
diff --git a/src/mame/audio/midway.h b/src/mame/audio/midway.h
index e248a75..3539441 100644
--- a/src/mame/audio/midway.h
+++ b/src/mame/audio/midway.h
@@ -28,7 +28,6 @@
 //**************************************************************************
 
 extern const device_type MIDWAY_SSIO;
-extern const device_type MIDWAY_CHIP_SQUEAK_DELUXE;
 extern const device_type MIDWAY_SOUNDS_GOOD;
 extern const device_type MIDWAY_TURBO_CHIP_SQUEAK;
 extern const device_type MIDWAY_SQUAWK_N_TALK;
@@ -108,46 +107,6 @@ private:
 };
 
 
-// ======================> midway_chip_squeak_deluxe_device
-
-class midway_chip_squeak_deluxe_device :    public device_t,
-											public device_mixer_interface
-{
-public:
-	// construction/destruction
-	midway_chip_squeak_deluxe_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-	// read/write
-	DECLARE_READ8_MEMBER(read);
-	DECLARE_WRITE8_MEMBER(write);
-	DECLARE_WRITE_LINE_MEMBER(reset_write);
-
-	// internal communications
-	DECLARE_WRITE8_MEMBER(porta_w);
-	DECLARE_WRITE8_MEMBER(portb_w);
-	DECLARE_WRITE_LINE_MEMBER(irq_w);
-	DECLARE_READ16_MEMBER(pia_r);
-	DECLARE_WRITE16_MEMBER(pia_w);
-
-protected:
-	// device-level overrides
-	virtual machine_config_constructor device_mconfig_additions() const override;
-	virtual void device_start() override;
-	virtual void device_reset() override;
-	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
-
-private:
-	// devices
-	required_device<m68000_device> m_cpu;
-	required_device<pia6821_device> m_pia;
-	required_device<dac_word_interface> m_dac;
-
-	// internal state
-	uint8_t m_status;
-	uint16_t m_dacval;
-};
-
-
 // ======================> midway_sounds_good_device
 
 class midway_sounds_good_device :   public device_t,
diff --git a/src/mame/audio/wow.cpp b/src/mame/audio/wow.cpp
deleted file mode 100644
index e09cd7b..0000000
--- a/src/mame/audio/wow.cpp
+++ /dev/null
@@ -1,183 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Mike Coates
-/**************************************************************************
-
-    WOW/Votrax SC-01 Emulator
-
-    Mike at Dissfulfils.co.uk
-
-        Modified to match phonemes to words
-
-        Ajudd at quantime.co.uk
-
-**************************************************************************
-
-wow_sh_start  - Start emulation, load samples from Votrax subdirectory
-wow_sh_w      - Write data to votrax port
-wow_sh_status - Return busy status (-1 = busy)
-wow_port_2_r  - Returns status of voice port
-wow_sh_ update- Null
-
-**************************************************************************/
-
-#include "emu.h"
-#include "cpu/z80/z80.h"
-#include "includes/astrocde.h"
-#include "audio/wow.h"
-
-/****************************************************************************
- * 64 Phonemes - currently 1 sample per phoneme, will be combined sometime!
- ****************************************************************************/
-
-static const char *const PhonemeTable[65] =
-{
-	"EH3","EH2","EH1","PA0","DT" ,"A1" ,"A2" ,"ZH",
-	"AH2","I3" ,"I2" ,"I1" ,"M"  ,"N"  ,"B"  ,"V",
-	"CH" ,"SH" ,"Z"  ,"AW1","NG" ,"AH1","OO1","OO",
-	"L"  ,"K"  ,"J"  ,"H"  ,"G"  ,"F"  ,"D"  ,"S",
-	"A"  ,"AY" ,"Y1" ,"UH3","AH" ,"P"  ,"O"  ,"I",
-	"U"  ,"Y"  ,"T"  ,"R"  ,"E"  ,"W"  ,"AE" ,"AE1",
-	"AW2","UH2","UH1","UH" ,"O2" ,"O1" ,"IU" ,"U1",
-	"THV","TH" ,"ER" ,"EH" ,"E1" ,"AW" ,"PA1","STOP",
-	nullptr
-};
-
-/* Missing samples : ready,  from,  one,  bite,  youl,  explode,  if,  myself,  back,
-   cant,  do,  wait,  worlings,  very,  babies,  breath,  fire,  beat,  rest,
-   then,  never,  worlock,  escape,  door,  try,  any,  harder,  only,  meet,  with,
-   doom,  pop,
-   Problems with YOU and YOU'LL and YOU'DD */
-
-static const char *const wowWordTable[] =
-{
-"AH1I3Y1", "UH1GA1EH1N", "AHAH2", "AE1EH3M", "AE1EH3ND",
-"anew.wav", "AH1NUHTHER", "AE1NY", "anyone.wav", "appear.wav", "AH1UH3R", "UHR", "BABYY1S", "BAE1EH3K",
-"BE1T", "become.wav", "BEHST", "BEH1TER", "BUH3AH2YT", "bones.wav", "BRE1YTH", "but.wav", "can.wav", "KAE1EH3NT",
-"chance.wav", "CHEHST", "KO1O2I3Y1N", "dance.wav", "DE1STRO1UH3I3AY",
-"DE1VEH1LUH3PT", "DIUU", "DONT", "DUUM", "DOO1R", "draw.wav", "DUHNJEH1N", "DUHNJEH1NZ",
-"each.wav", "eaten.wav", "EHSPA0KA2I3Y1P", "EHKPA0SPLOU1D", "fear.wav", "FAH1I3YND", "FAH1I3Y1ND", "FAH1EH3AYR", "FOR", "FRUHMM",
-"garwor.wav", "GEHT", "GEH1T", "GEHEH3T", "GEHTING", "good.wav", "HAH1HAH1HAH1HAH1", "HAH1RDER",
-"hasnt.wav", "have.wav", "HEH1I3VE1WA1I3Y1TS", "HAI1Y1", "HOP",
-"HUHNGRY", "HUHNGGRY", "HERRY", "AH1EH3I3Y", "AH1UH3I3Y", "IF", "I1F", "AH1I3YM", "AH1EH3I3YL", "AH1I3Y1L", "IN1",
-"INSERT", "invisibl.wav", "IT", "lie.wav", "MAE1EH3DJI1KUH1L",
-"MAE1EH3DJI1KUH1L", "MEE1", "MEE1T", "months.wav",
-"MAH1EH3I3Y", "MAH2AH2EH3I3Y", "MAH1I1Y", "MAH1I3Y1", "MAH1I3Y", "MAH1I3YSEHLF", "near.wav", "NEH1VER",
-"NAH1UH3U1", "UHV", "AWF", "WUHN", "O1NLY", "UHVEHN", "PA1", "PEHTS", "PAH1WERFUH1L", "PAH1P",
-"radar.wav", "REHDY",
-"REHST", "say.wav", "SAH1I3AYEHNS", "SE1Y", "PA0", "start.wav", "THVAYAY", "THVUH", "THVUH1", "THUH1", "THVEH1N",
-"THVRU", "thurwor.wav", "time.wav", "TU1", "TUU1", "TIUU1", "TREH1ZHERT", "TRAH1EH3I3Y", "VEHEH3RY", "WA2AYYT",
-"WOO1R", "WORYER", "watch.wav", "WE1Y", "WEHLKUHM",
-"WERR", "WAH1EH3I3L", "WIL", "WITH", "WIZERD", "wont.wav",
-"WO1O2R", "WO1ERLD", "WORLINGS", "WORLUHK",
-"YI3U", "Y1IUU", "YIUUI", "Y1IUU1U1", "YI3U1", "Y1IUUL", "YIUU1L", "Y1IUUD", "YO2O2R",nullptr
-};
-
-#define num_samples (sizeof(wowWordTable)/sizeof(char *))
-
-
-const char *const wow_sample_names[] =
-{
-	"*wow",
-	"a", "again", "ahh", "am", "and",
-	"anew", "another", "any", "anyone", "appear", "are", "are", "babies", "back",
-	"beat", "become", "best", "better", "bite", "bones", "breath", "but", "can", "cant",
-	"chance", "chest", "coin", "dance", "destroy",
-	"develop", "do", "dont", "doom", "door", "draw", "dungeon", "dungeons",
-	"each", "eaten", "escape", "explode", "fear", "find", "find", "fire", "for", "from",
-	"garwor", "get", "get", "get", "getting", "good", "hahahaha", "harder",
-	"hasnt", "have", "heavyw", "hey", "hope",
-	"hungry", "hungry", "hurry", "i", "i", "if", "if", "im", "i1", "ill", "in",
-	"insert", "invisibl", "it", "lie", "magic",
-	"magical", "me", "meet", "months",
-	"my", "my", "my", "my", "my", "myself", "near", "never",
-	"now", "of", "off", "one", "only", "oven", "pause", "pets", "powerful", "pop",
-	"radar", "ready",
-	"rest", "say", "science", "see", "spause", "start", "the", "the", "the", "the", "then",
-	"through", "thurwor", "time", "to", "to", "to", "treasure", "try", "very", "wait",
-	"war", "warrior", "watch", "we", "welcome",
-	"were", "while", "will", "with", "wizard", "wont",
-	"wor", "world", "worlings", "worlock",
-	"you", "you", "you", "you", "you", "youl", "youl", "youd", "your",nullptr
-};
-
-
-READ8_MEMBER( astrocde_state::wow_speech_r )
-{
-	uint8_t data = offset >> 8;
-#if USE_FAKE_VOTRAX
-	int Phoneme/*, Intonation*/;
-	int i = 0;
-	offset &= 0xff;
-
-	m_totalword_ptr = m_totalword;
-
-	Phoneme = data & 0x3F;
-	//Intonation = data >> 6;
-
-	//logerror("Data : %d Speech : %s at intonation %d\n",Phoneme, PhonemeTable[Phoneme],Intonation);
-
-	if(Phoneme==63) {
-		m_samples->stop(0);
-		//logerror("Clearing sample %s\n",m_totalword);
-		m_totalword[0] = 0;                 /* Clear the total word stack */
-		return data;
-	}
-	if (Phoneme==3)                        /* We know PA0 is never part of a word */
-		m_totalword[0] = 0;                 /* Clear the total word stack */
-
-	/* Phoneme to word translation */
-
-	if (*(m_totalword) == 0) {
-		strcpy(m_totalword,PhonemeTable[Phoneme]);                      /* Copy over the first phoneme */
-		if (m_plural != 0) {
-			//logerror("found a possible plural at %d\n",m_plural-1);
-			if (!strcmp("S",m_totalword)) {         /* Plural check */
-				m_samples->start(0, num_samples-2);      /* play the sample at position of word */
-				m_samples->set_frequency(0, 11025);    /* play at correct rate */
-				m_totalword[0] = 0;                 /* Clear the total word stack */
-				m_oldword[0] = 0;                   /* Clear the total word stack */
-				return data;
-			} else {
-					m_plural=0;
-			}
-		}
-	} else
-		strcat(m_totalword,PhonemeTable[Phoneme]);                      /* Copy over the first phoneme */
-
-	//logerror("Total word = %s\n",m_totalword);
-
-	for (i=0; wowWordTable[i]; i++) {
-		if (!strcmp(wowWordTable[i],m_totalword)) {         /* Scan the word (sample) table for the complete word */
-			/* WOW has Dungeon */
-			if ((!strcmp("GDTO1RFYA2N",m_totalword)) || (!strcmp("RO1U1BAH1T",m_totalword)) || (!strcmp("KO1UH3I3E1N",m_totalword))) {        /* May be plural */
-				m_plural=i+1;
-				strcpy(m_oldword,m_totalword);
-				//logerror("Storing sample position %d and copying string %s\n",m_plural,m_oldword);
-			} else {
-				m_plural=0;
-			}
-			m_samples->start(0, i);                      /* play the sample at position of word */
-			m_samples->set_frequency(0, 11025);         /* play at correct rate */
-			//logerror("Playing sample %d\n",i);
-			m_totalword[0] = 0;                 /* Clear the total word stack */
-			return data;
-		}
-	}
-#else
-	m_votrax->inflection_w(space, 0, data >> 6);
-	m_votrax->write(space, 0, data);
-#endif
-
-	/* Note : We should really also use volume in this as well as frequency */
-	return data;                                   /* Return nicely */
-}
-
-
-CUSTOM_INPUT_MEMBER( astrocde_state::wow_speech_status_r )
-{
-#if USE_FAKE_VOTRAX
-	return !m_samples->playing(0);
-#else
-	return m_votrax->request();
-#endif
-}
diff --git a/src/mame/audio/wow.h b/src/mame/audio/wow.h
deleted file mode 100644
index a523dbb..0000000
--- a/src/mame/audio/wow.h
+++ /dev/null
@@ -1,4 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Mike Coates
-
-extern const char *const wow_sample_names[];
diff --git a/src/mame/drivers/24cdjuke.cpp b/src/mame/drivers/24cdjuke.cpp
index eb0a0de..9d84a16 100644
--- a/src/mame/drivers/24cdjuke.cpp
+++ b/src/mame/drivers/24cdjuke.cpp
@@ -293,7 +293,7 @@ static MACHINE_CONFIG_START( midcoin24cdjuke, midcoin24cdjuke_state )
 	MCFG_I8255_OUT_PORTC_CB(WRITE8(midcoin24cdjuke_state, kb_col_w))
 
 	MCFG_DEVICE_ADD("ic31", I8255A, 0)
-	MCFG_I8255_OUT_PORTB_CB(LOGGER("PPI8255 - unmapped write port B", 0))
+	MCFG_I8255_OUT_PORTB_CB(LOGGER("PPI8255 - unmapped write port B"))
 	MCFG_I8255_IN_PORTC_CB(IOPORT("MD4"))
 MACHINE_CONFIG_END
 
diff --git a/src/mame/drivers/4enraya.cpp b/src/mame/drivers/4enraya.cpp
index f259e28..a546f76 100644
--- a/src/mame/drivers/4enraya.cpp
+++ b/src/mame/drivers/4enraya.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina, Roberto Fresca
 /***************************************************************************
 
diff --git a/src/mame/drivers/8080bw.cpp b/src/mame/drivers/8080bw.cpp
index 06c5904..eaf560c 100644
--- a/src/mame/drivers/8080bw.cpp
+++ b/src/mame/drivers/8080bw.cpp
@@ -3815,8 +3815,8 @@ ROM_START( moonbase )
 	ROM_LOAD( "ze3-10.f5",    0x4400, 0x0400, CRC(1e7c22a4) SHA1(b34173375494ffbf5400dd4014a683a9807f4f08) )
 
 	ROM_REGION( 0x0800, "proms", 0 )        /* color maps player 1/player 2 */
-	ROM_LOAD( "cv02.h7",      0x0000, 0x0400, CRC(2bdf83a0) SHA1(01ffbd43964c41987e7d44816271308f9a70802b) ) /* NEC B406 or compatible BPROM, like the 82S137 */
-	ROM_LOAD( "cv01.g7",      0x0400, 0x0400, CRC(aac24f34) SHA1(ad110e776547fb48baac568bb50d61854537ca34) ) /* NEC B406 or compatible BPROM, like the 82S137 */
+	ROM_LOAD( "cv02.h7",      0x0400, 0x0400, CRC(2bdf83a0) SHA1(01ffbd43964c41987e7d44816271308f9a70802b) ) /* NEC B406 or compatible BPROM, like the 82S137 */
+	ROM_LOAD( "cv01.g7",      0x0000, 0x0400, CRC(aac24f34) SHA1(ad110e776547fb48baac568bb50d61854537ca34) ) /* NEC B406 or compatible BPROM, like the 82S137 */
 ROM_END
 
 ROM_START( moonbasea )
@@ -3833,8 +3833,8 @@ ROM_START( moonbasea )
 	ROM_LOAD( "ze3-10.f5",    0x4400, 0x0400, CRC(1e7c22a4) SHA1(b34173375494ffbf5400dd4014a683a9807f4f08) )
 
 	ROM_REGION( 0x0800, "proms", 0 )        /* color maps player 1/player 2 */
-	ROM_LOAD( "cv02.h7",      0x0000, 0x0400, CRC(2bdf83a0) SHA1(01ffbd43964c41987e7d44816271308f9a70802b) ) /* NEC B406 or compatible BPROM, like the 82S137 */
-	ROM_LOAD( "cv01.g7",      0x0400, 0x0400, CRC(aac24f34) SHA1(ad110e776547fb48baac568bb50d61854537ca34) ) /* NEC B406 or compatible BPROM, like the 82S137 */
+	ROM_LOAD( "cv02.h7",      0x0400, 0x0400, CRC(2bdf83a0) SHA1(01ffbd43964c41987e7d44816271308f9a70802b) ) /* NEC B406 or compatible BPROM, like the 82S137 */
+	ROM_LOAD( "cv01.g7",      0x0000, 0x0400, CRC(aac24f34) SHA1(ad110e776547fb48baac568bb50d61854537ca34) ) /* NEC B406 or compatible BPROM, like the 82S137 */
 ROM_END
 
 
diff --git a/src/mame/drivers/aa310.cpp b/src/mame/drivers/aa310.cpp
index 1a332d0..6a3aa2f 100644
--- a/src/mame/drivers/aa310.cpp
+++ b/src/mame/drivers/aa310.cpp
@@ -124,7 +124,6 @@ protected:
 
 WRITE_LINE_MEMBER(aa310_state::aa310_wd177x_intrq_w)
 {
-	printf("%d IRQ\n",state);
 	if (state)
 	{
 		archimedes_request_fiq(ARCHIMEDES_FIQ_FLOPPY);
@@ -135,7 +134,6 @@ WRITE_LINE_MEMBER(aa310_state::aa310_wd177x_intrq_w)
 
 WRITE_LINE_MEMBER(aa310_state::aa310_wd177x_drq_w)
 {
-	printf("%d DRQ\n",state);
 	if (state)
 	{
 		archimedes_request_fiq(ARCHIMEDES_FIQ_FLOPPY_DRQ);
@@ -403,10 +401,7 @@ static MACHINE_CONFIG_START( aa310, aa310_state )
 
 	/* video hardware */
 	MCFG_SCREEN_ADD("screen", RASTER)
-	MCFG_SCREEN_REFRESH_RATE(60)
-	MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */
-	MCFG_SCREEN_SIZE(1280, 1024) //TODO: default screen size
-	MCFG_SCREEN_VISIBLE_AREA(0*8, 1280 - 1, 0*16, 1024 - 1)
+	MCFG_SCREEN_RAW_PARAMS(XTAL_16MHz,1024,0,735,624/2,0,292) // RiscOS 3 default screen settings
 	MCFG_SCREEN_UPDATE_DRIVER(archimedes_state, screen_update)
 
 	MCFG_PALETTE_ADD("palette", 32768)
@@ -415,6 +410,7 @@ static MACHINE_CONFIG_START( aa310, aa310_state )
 	MCFG_RAM_DEFAULT_SIZE("1M")
 
 	MCFG_WD1772_ADD("fdc", 8000000 / 1) // TODO: frequency
+	MCFG_WD_FDC_DISABLE_MOTOR_CONTROL
 	MCFG_WD_FDC_INTRQ_CALLBACK(WRITELINE(aa310_state, aa310_wd177x_intrq_w))
 	MCFG_WD_FDC_DRQ_CALLBACK(WRITELINE(aa310_state, aa310_wd177x_drq_w))
 	MCFG_FLOPPY_DRIVE_ADD("fdc:0", aa310_floppies, "35dd", aa310_state::floppy_formats)
diff --git a/src/mame/drivers/adp.cpp b/src/mame/drivers/adp.cpp
index ed6b53b..ee1c0d3 100644
--- a/src/mame/drivers/adp.cpp
+++ b/src/mame/drivers/adp.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /*
 
diff --git a/src/mame/drivers/aerofgt.cpp b/src/mame/drivers/aerofgt.cpp
index bc3e201..9846b97 100644
--- a/src/mame/drivers/aerofgt.cpp
+++ b/src/mame/drivers/aerofgt.cpp
@@ -2570,40 +2570,74 @@ ROM_START( karatblzbl )
 	ROM_LOAD16_BYTE( "8.u65",        0x080001, 0x040000, CRC(b491201a) SHA1(c18cb1cc8a8bf031e00d8d89de62f7ed5548e767) )
 ROM_END
 
+ROM_START( turbofrc ) // World version with no copyright notice
+	ROM_REGION( 0xc0000, "maincpu", 0 ) /* 68000 code */
+	ROM_LOAD16_WORD_SWAP( "4v2.subpcb.u2", 0x00000, 0x40000, CRC(721300ee) SHA1(79ab32fdfd377592a0bdbd1c4794cfd529a3eb7b) ) // 27c2048 - located on a OR-10 SUB BOARD - 4 stamped on chip with VideoSystem logo V
+	ROM_LOAD16_WORD_SWAP( "4v1.subpcb.u1", 0x40000, 0x40000, CRC(6cd5312b) SHA1(57b109fe268fb963e981c91b6d288667a3c9a665) ) // 27c2048 - located on a OR-10 SUB BOARD - 4 stamped on chip with VideoSystem logo V
+	ROM_LOAD16_WORD_SWAP( "4v3.u14",       0x80000, 0x40000, CRC(63f50557) SHA1(f8dba8c9ba412c9a67457ec31a804c57593ab20b) ) // 27c2048 - 4 stamped on chip with VideoSystem logo V
+
+	ROM_REGION( 0x30000, "audiocpu", 0 )    /* 64k for the audio CPU + banks */
+	ROM_LOAD( "6.u166", 0x00000, 0x20000, CRC(2ca14a65) SHA1(95f6e7b4fa7ca26872ff472d7e6fb75fd4f281d5) ) // 27c1001
+	ROM_RELOAD(         0x10000, 0x20000 )
+
+	ROM_REGION( 0x0a0000, "gfx1", 0 )
+	ROM_LOAD( "lh534ggs.u94", 0x000000, 0x80000, CRC(baa53978) SHA1(7f103122dd0bf675226ccf309fba73f645e0c79b) ) // mask rom
+	ROM_LOAD( "7.u95",        0x080000, 0x20000, CRC(71a6c573) SHA1(f14ebca676d85fabcde27631145933abc376dd12) ) // 27c1001a
+
+	ROM_REGION( 0x0a0000, "gfx2", 0 )
+	ROM_LOAD( "lh534ggy.u105", 0x000000, 0x80000, CRC(4de4e59e) SHA1(571396dadb8aac043319cabe24e629210e442d57) ) // mask rom
+	ROM_LOAD( "8.u106",        0x080000, 0x20000, CRC(c6479eb5) SHA1(47a58f082c73bc9dae3970e760ba46478ce6a190) ) // 27c1001a
+
+	ROM_REGION( 0x200000, "spritegfx", 0 )
+	ROM_LOAD( "lh534gh2.u116", 0x000000, 0x80000, CRC(df210f3b) SHA1(990ac43e4a46fee6b929c5b27d317cdadf179b8b) ) // mask rom
+	ROM_LOAD( "5.u118",        0x080000, 0x40000, CRC(f61d1d79) SHA1(2b8e33912c05c26170afd2fced0ff06cb7a097fa) ) // 27c2048
+	ROM_LOAD( "lh534gh1.u117", 0x100000, 0x80000, CRC(f70812fd) SHA1(1964e1134940825211cd4825fdd3f13b8242192d) ) // mask rom
+	ROM_LOAD( "4.u119",        0x180000, 0x40000, CRC(474ea716) SHA1(67753e96fa4fc8cd689a8bddeb60dbde259cacaa) ) // 27c2048
+
+	ROM_REGION( 0x080000, "gfx4", 0 )
+	ROM_LOAD( "lh532a52.u134", 0x000000, 0x40000, CRC(3c725a48) SHA1(120e62b2ef911bfa0f8a1468966ff70fab2d7582) ) // mask rom
+	ROM_LOAD( "lh532a51.u135", 0x040000, 0x40000, CRC(95c63559) SHA1(5f77bd22dce1ac4aa7291e5c3c3c358e2f066e8c) ) // mask rom
+
+	ROM_REGION( 0x40000, "ymsnd.deltat", 0 ) /* sound samples */
+	ROM_LOAD( "lh532h74.u180", 0x00000, 0x40000, CRC(a3d43254) SHA1(d0225d6cf9299ecc39d8e3f64f48cf80d554a67f) ) // mask rom
+
+	ROM_REGION( 0x100000, "ymsnd", 0 ) /* sound samples */
+	ROM_LOAD( "lh538o7j.u179", 0x000000, 0x100000, CRC(60ca0333) SHA1(28b94edc98d360386759780ccd1122d43ffa5279) ) // mask rom
+ROM_END
 
-ROM_START( turbofrc )
+ROM_START( turbofrcu ) // US version: most notable thing in there is the points value of the rocks in level 6 (5,000 versus 500).
 	ROM_REGION( 0xc0000, "maincpu", 0 ) /* 68000 code */
-	ROM_LOAD16_WORD_SWAP( "tfrc2.bin",    0x00000, 0x40000, CRC(721300ee) SHA1(79ab32fdfd377592a0bdbd1c4794cfd529a3eb7b) )
-	ROM_LOAD16_WORD_SWAP( "tfrc1.bin",    0x40000, 0x40000, CRC(6cd5312b) SHA1(57b109fe268fb963e981c91b6d288667a3c9a665) )
-	ROM_LOAD16_WORD_SWAP( "tfrc3.bin",    0x80000, 0x40000, CRC(63f50557) SHA1(f8dba8c9ba412c9a67457ec31a804c57593ab20b) )
+	ROM_LOAD16_WORD_SWAP( "8v2.subpcb.u2", 0x00000, 0x40000, CRC(721300ee) SHA1(79ab32fdfd377592a0bdbd1c4794cfd529a3eb7b) ) // 27c2048 - located on a OR-10 SUB BOARD - 8 stamped on chip with VideoSystem logo V
+	ROM_LOAD16_WORD_SWAP( "8v1.subpcb.u1", 0x40000, 0x40000, CRC(cc324da6) SHA1(ed2eaff7351914e3ebaf925ddc01be9d44d89fa6) ) // 27c2048 - located on a OR-10 SUB BOARD - 8 stamped on chip with VideoSystem logo V
+	ROM_LOAD16_WORD_SWAP( "8v3.u14",       0x80000, 0x40000, CRC(c0a15480) SHA1(1ec99382e0a00a8167773b1d454a63cc5cd6199c) ) // 27c2048 - 8 stamped on chip with VideoSystem logo V
 
 	ROM_REGION( 0x30000, "audiocpu", 0 )    /* 64k for the audio CPU + banks */
-	ROM_LOAD( "tfrcu166.bin", 0x00000, 0x20000, CRC(2ca14a65) SHA1(95f6e7b4fa7ca26872ff472d7e6fb75fd4f281d5) )
-	ROM_RELOAD(               0x10000, 0x20000 )
+	ROM_LOAD( "6.u166", 0x00000, 0x20000, CRC(2ca14a65) SHA1(95f6e7b4fa7ca26872ff472d7e6fb75fd4f281d5) ) // 27c1001
+	ROM_RELOAD(         0x10000, 0x20000 )
 
 	ROM_REGION( 0x0a0000, "gfx1", 0 )
-	ROM_LOAD( "tfrcu94.bin",  0x000000, 0x80000, CRC(baa53978) SHA1(7f103122dd0bf675226ccf309fba73f645e0c79b) )
-	ROM_LOAD( "tfrcu95.bin",  0x080000, 0x20000, CRC(71a6c573) SHA1(f14ebca676d85fabcde27631145933abc376dd12) )
+	ROM_LOAD( "lh534ggs.u94", 0x000000, 0x80000, CRC(baa53978) SHA1(7f103122dd0bf675226ccf309fba73f645e0c79b) ) // mask rom
+	ROM_LOAD( "7.u95",        0x080000, 0x20000, CRC(71a6c573) SHA1(f14ebca676d85fabcde27631145933abc376dd12) ) // 27c1001a
 
 	ROM_REGION( 0x0a0000, "gfx2", 0 )
-	ROM_LOAD( "tfrcu105.bin", 0x000000, 0x80000, CRC(4de4e59e) SHA1(571396dadb8aac043319cabe24e629210e442d57) )
-	ROM_LOAD( "tfrcu106.bin", 0x080000, 0x20000, CRC(c6479eb5) SHA1(47a58f082c73bc9dae3970e760ba46478ce6a190) )
+	ROM_LOAD( "lh534ggy.u105", 0x000000, 0x80000, CRC(4de4e59e) SHA1(571396dadb8aac043319cabe24e629210e442d57) ) // mask rom
+	ROM_LOAD( "8.u106",        0x080000, 0x20000, CRC(c6479eb5) SHA1(47a58f082c73bc9dae3970e760ba46478ce6a190) ) // 27c1001a
 
 	ROM_REGION( 0x200000, "spritegfx", 0 )
-	ROM_LOAD( "tfrcu116.bin", 0x000000, 0x80000, CRC(df210f3b) SHA1(990ac43e4a46fee6b929c5b27d317cdadf179b8b) )
-	ROM_LOAD( "tfrcu118.bin", 0x080000, 0x40000, CRC(f61d1d79) SHA1(2b8e33912c05c26170afd2fced0ff06cb7a097fa) )
-	ROM_LOAD( "tfrcu117.bin", 0x100000, 0x80000, CRC(f70812fd) SHA1(1964e1134940825211cd4825fdd3f13b8242192d) )
-	ROM_LOAD( "tfrcu119.bin", 0x180000, 0x40000, CRC(474ea716) SHA1(67753e96fa4fc8cd689a8bddeb60dbde259cacaa) )
+	ROM_LOAD( "lh534gh2.u116", 0x000000, 0x80000, CRC(df210f3b) SHA1(990ac43e4a46fee6b929c5b27d317cdadf179b8b) ) // mask rom
+	ROM_LOAD( "5.u118",        0x080000, 0x40000, CRC(f61d1d79) SHA1(2b8e33912c05c26170afd2fced0ff06cb7a097fa) ) // 27c2048
+	ROM_LOAD( "lh534gh1.u117", 0x100000, 0x80000, CRC(f70812fd) SHA1(1964e1134940825211cd4825fdd3f13b8242192d) ) // mask rom
+	ROM_LOAD( "4.u119",        0x180000, 0x40000, CRC(474ea716) SHA1(67753e96fa4fc8cd689a8bddeb60dbde259cacaa) ) // 27c2048
 
-	ROM_REGION( 0x100000, "gfx4", 0 )
-	ROM_LOAD( "tfrcu134.bin", 0x000000, 0x80000, CRC(487330a2) SHA1(0bd36c1f5776ba2773f621e9bcb22f56ed1d84ec) )
-	ROM_LOAD( "tfrcu135.bin", 0x080000, 0x80000, CRC(3a7e5b6d) SHA1(0079ffaa1bf93a5087c75615c78ec596b28c9a32) )
+	ROM_REGION( 0x080000, "gfx4", 0 )
+	ROM_LOAD( "lh532a52.u134", 0x000000, 0x40000, CRC(3c725a48) SHA1(120e62b2ef911bfa0f8a1468966ff70fab2d7582) ) // mask rom
+	ROM_LOAD( "lh532a51.u135", 0x040000, 0x40000, CRC(95c63559) SHA1(5f77bd22dce1ac4aa7291e5c3c3c358e2f066e8c) ) // mask rom
 
-	ROM_REGION( 0x20000, "ymsnd.deltat", 0 ) /* sound samples */
-	ROM_LOAD( "tfrcu180.bin",   0x00000, 0x20000, CRC(39c7c7d5) SHA1(66ee9f7cbc18ffab2c70f77ab0edead6bb018ca9) )
+	ROM_REGION( 0x40000, "ymsnd.deltat", 0 ) /* sound samples */
+	ROM_LOAD( "lh532h74.u180", 0x00000, 0x40000, CRC(a3d43254) SHA1(d0225d6cf9299ecc39d8e3f64f48cf80d554a67f) ) // mask rom
 
 	ROM_REGION( 0x100000, "ymsnd", 0 ) /* sound samples */
-	ROM_LOAD( "tfrcu179.bin", 0x000000, 0x100000, CRC(60ca0333) SHA1(28b94edc98d360386759780ccd1122d43ffa5279) )
+	ROM_LOAD( "lh538o7j.u179", 0x000000, 0x100000, CRC(60ca0333) SHA1(28b94edc98d360386759780ccd1122d43ffa5279) ) // mask rom
 ROM_END
 
 ROM_START( aerofgt )
@@ -2830,8 +2864,8 @@ GAME( 1991, karatblzu,karatblz, karatblz, karatblz, driver_device, 0, ROT0,   "V
 GAME( 1991, karatblzj,karatblz, karatblz, karatblz, driver_device, 0, ROT0,   "Video System Co.", "Toushin Blazers (Japan)", MACHINE_SUPPORTS_SAVE | MACHINE_NO_COCKTAIL )
 GAME( 1991, karatblzbl,karatblz,karatblzbl,karatblz,driver_device, 0, ROT0,   "bootleg",          "Karate Blazers (bootleg with Street Smart sound hardware)", MACHINE_SUPPORTS_SAVE | MACHINE_NO_COCKTAIL | MACHINE_IMPERFECT_SOUND )
 
-GAME( 1991, turbofrc, 0,        turbofrc, turbofrc, driver_device, 0, ROT270, "Video System Co.", "Turbo Force (old revision)", MACHINE_SUPPORTS_SAVE | MACHINE_NO_COCKTAIL )
-// there's also an undumped Turbo Force (new revision). Most notable thing in there is the points value of the rocks in level 6 (5.000 versus 500).
+GAME( 1991, turbofrc, 0,        turbofrc, turbofrc, driver_device, 0, ROT270, "Video System Co.", "Turbo Force (World)", MACHINE_SUPPORTS_SAVE | MACHINE_NO_COCKTAIL )
+GAME( 1991, turbofrcu,turbofrc, turbofrc, turbofrc, driver_device, 0, ROT270, "Video System Co.", "Turbo Force (US)", MACHINE_SUPPORTS_SAVE | MACHINE_NO_COCKTAIL )
 
 // the tiles on these also contain an alt title 'The Final War' for both the title screen and attract logo was it ever used?
 GAME( 1992, aerofgt,  0,        aerofgt,  aerofgt, driver_device,  0, ROT270, "Video System Co.", "Aero Fighters (World / USA + Canada / Korea / Hong Kong / Taiwan) (newer hardware)", MACHINE_SUPPORTS_SAVE | MACHINE_NO_COCKTAIL ) // this has the newer sprite chip etc. unlike all other games in this driver..
diff --git a/src/mame/drivers/airraid.cpp b/src/mame/drivers/airraid.cpp
index 66dca1c..4d38e6d 100644
--- a/src/mame/drivers/airraid.cpp
+++ b/src/mame/drivers/airraid.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina, Angelo Salese, hap
 /* Air Raid (aka Cross Shooter) (c) 1987 Seibu
 
diff --git a/src/mame/drivers/amstrad.cpp b/src/mame/drivers/amstrad.cpp
index bcd466c..4cc247e 100644
--- a/src/mame/drivers/amstrad.cpp
+++ b/src/mame/drivers/amstrad.cpp
@@ -235,7 +235,7 @@ static INPUT_PORTS_START( amstrad_keyboard )
 	PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD)                                    PORT_CODE(KEYCODE_Q)          PORT_CHAR('q') PORT_CHAR('Q')
 	PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Tab")                   PORT_CODE(KEYCODE_TAB)        PORT_CHAR(9)
 	PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD)                                    PORT_CODE(KEYCODE_A)          PORT_CHAR('a') PORT_CHAR('A')
-	PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Caps Lock")             PORT_CODE(KEYCODE_CAPSLOCK)   PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) PORT_TOGGLE
+	PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Caps Lock")             PORT_CODE(KEYCODE_CAPSLOCK)   PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) // No physical toggle
 	PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD)                                    PORT_CODE(KEYCODE_Z)          PORT_CHAR('z') PORT_CHAR('Z')
 
 	PORT_START("kbrow.9")
diff --git a/src/mame/drivers/amusco.cpp b/src/mame/drivers/amusco.cpp
index 06ecffe..b367be6 100644
--- a/src/mame/drivers/amusco.cpp
+++ b/src/mame/drivers/amusco.cpp
@@ -91,6 +91,7 @@
 #include "machine/pic8259.h"
 #include "machine/pit8253.h"
 #include "machine/msm5832.h"
+#include "machine/ticket.h"
 #include "amusco.lh"
 
 
@@ -102,10 +103,12 @@ public:
 		m_videoram(*this, "videoram"),
 		m_maincpu(*this, "maincpu"),
 		m_gfxdecode(*this, "gfxdecode"),
+		m_pit(*this, "pit8253"),
 		m_pic(*this, "pic8259"),
 		m_rtc(*this, "rtc"),
 		m_crtc(*this, "crtc"),
-		m_screen(*this, "screen")
+		m_screen(*this, "screen"),
+		m_hopper(*this, "hopper")
 		{ }
 
 	required_shared_ptr<uint8_t> m_videoram;
@@ -128,10 +131,12 @@ public:
 
 	required_device<cpu_device> m_maincpu;
 	required_device<gfxdecode_device> m_gfxdecode;
+	required_device<pit8253_device> m_pit;
 	required_device<pic8259_device> m_pic;
 	required_device<msm5832_device> m_rtc;
 	required_device<mc6845_device> m_crtc;
 	required_device<screen_device> m_screen;
+	required_device<ticket_dispenser_device> m_hopper;
 	uint8_t m_mc6845_address;
 	uint16_t m_video_update_address;
 };
@@ -240,22 +245,39 @@ WRITE8_MEMBER(amusco_state::output_b_w)
   7654 3210
   ---- --x-  Unknown lamp (lits when all holds/disc are ON. Could be a Cancel lamp in an inverted Hold system).
   ---- -x--  Start/Draw lamp.
-  ---x ----  Low when sound data queued.
-  --x- ----  Safe to shutdown?
-  -x-- ----  Allow NMI?
-  x--- x--x  Unknown.
+  ---- x--x  Unknown.
+  ---x ----  Special: low when sound data queued.
+  --x- ----  Special: set by NMI routine (trigger shutdown?)
+  -x-- ----  Special: cleared in NMI routine (safe to shutdown?)
+  x--- ----  Special: NMI enable (cleared and set along with CPU interrupt flag).
 
 */
 	output().set_lamp_value(6, (data >> 2) & 1);    // Lamp 6 (Start/Draw)
 	output().set_lamp_value(7, (data >> 1) & 1);    // Lamp 7 (Unknown)
 
-	//machine().bookkeeping().coin_counter_w(0, ~data & 0x10); // Probably not coin-related
+	m_pit->write_gate0(!BIT(data, 4));
 
 //  logerror("Writing %02Xh to PPI output B\n", data);
 }
 
 WRITE8_MEMBER(amusco_state::output_c_w)
 {
+/* Lamps and counters from port C
+
+  7654 3210
+  ---- ---x  Unknown (used by Draw 88 Poker only?)
+  ---- --x-  Coin counter (bills not included).
+  ---- -x--  Unknown counter (points won?)
+  ---- x---  Unknown counter (points played?)
+  ---x ----  Coin out pulse.
+  xxx- ----  Unused.
+*/
+	if (!data)
+		return;
+
+	machine().bookkeeping().coin_counter_w(0, !BIT(data, 1));
+	m_hopper->motor_w(BIT(data, 4));
+
 //  logerror("Writing %02Xh to PPI output C\n", data);
 }
 
@@ -475,6 +497,8 @@ static MACHINE_CONFIG_START( amusco, amusco_state )
 	MCFG_I8155_IN_PORTC_CB(DEVREAD8("rtc", msm5832_device, data_r))
 	MCFG_I8155_OUT_PORTC_CB(DEVWRITE8("rtc", msm5832_device, data_w))
 
+	MCFG_TICKET_DISPENSER_ADD("hopper", attotime::from_msec(30), TICKET_MOTOR_ACTIVE_LOW, TICKET_STATUS_ACTIVE_HIGH)
+
 	/* video hardware */
 	MCFG_SCREEN_ADD("screen", RASTER)
 	MCFG_SCREEN_REFRESH_RATE(60)
diff --git a/src/mame/drivers/apricot.cpp b/src/mame/drivers/apricot.cpp
index eb7d916..b602f15 100644
--- a/src/mame/drivers/apricot.cpp
+++ b/src/mame/drivers/apricot.cpp
@@ -4,7 +4,9 @@
 
     ACT Apricot PC/Xi
 
-    - Error 29 (timer failed)
+    TODO:
+    - External RS232 data transfers to the Apricot are usually garbage (but
+      sending to an external target works fine)
     - Dump of the keyboard MCU ROM needed (can be dumped using test mode)
 
 ***************************************************************************/
@@ -25,6 +27,7 @@
 #include "bus/rs232/rs232.h"
 #include "bus/apricot/expansion/expansion.h"
 #include "bus/apricot/keyboard/keyboard.h"
+#include "softlist.h"
 
 
 //**************************************************************************
@@ -311,7 +314,7 @@ MC6845_UPDATE_ROW( apricot_state::crtc_update_row )
 			for (int x = 0; x <= 10; x++)
 			{
 				int color = fill ? 1 : BIT(data, x);
-				if (BIT(code, 15)) color = !color; // reverse?
+				color ^= BIT(code, 15); // reverse?
 				bitmap.pix32(y, x + i*10) = pen[color ? 1 + BIT(code, 14) : 0];
 			}
 		}
@@ -441,12 +444,12 @@ static MACHINE_CONFIG_START( apricot, apricot_state )
 
 	// rs232 port
 	MCFG_RS232_PORT_ADD("rs232", default_rs232_devices, nullptr)
-// note: missing a receive clock callback to support external clock mode
-// (m_data_selector_rts == 1 and m_data_selector_dtr == 0)
+	// note: missing a receive clock callback to support external clock mode
+	// (m_data_selector_rts == 1 and m_data_selector_dtr == 0)
 	MCFG_RS232_RXD_HANDLER(DEVWRITELINE("ic15", z80sio0_device, rxa_w))
 	MCFG_RS232_DCD_HANDLER(DEVWRITELINE("ic15", z80sio0_device, dcda_w))
 	MCFG_RS232_DSR_HANDLER(DEVWRITELINE("ic15", z80sio0_device, synca_w))
-	MCFG_RS232_CTS_HANDLER(DEVWRITELINE("ic15", z80sio0_device, ctsa_w))
+	MCFG_RS232_CTS_HANDLER(DEVWRITELINE("ic15", z80sio0_device, ctsa_w))  MCFG_DEVCB_XOR(1)
 
 	// keyboard
 	MCFG_APRICOT_KEYBOARD_INTERFACE_ADD("kbd", "hle")
@@ -471,6 +474,8 @@ static MACHINE_CONFIG_START( apricot, apricot_state )
 	MCFG_FLOPPY_DRIVE_ADD("ic68:0", apricot_floppies, "d32w", apricot_state::floppy_formats)
 	MCFG_FLOPPY_DRIVE_ADD("ic68:1", apricot_floppies, "d32w", apricot_state::floppy_formats)
 
+	MCFG_SOFTWARE_LIST_ADD("flop_list", "apricot_flop")
+
 	// expansion bus
 	MCFG_EXPANSION_ADD("exp", "ic91")
 	MCFG_EXPANSION_IOP_ADD("ic71")
@@ -504,5 +509,5 @@ ROM_END
 //**************************************************************************
 
 //    YEAR  NAME       PARENT   COMPAT  MACHINE    INPUT  CLASS          INIT  COMPANY  FULLNAME      FLAGS
-COMP( 1983, apricot,   0,       0,      apricot,   0,     driver_device, 0,    "ACT",   "Apricot PC", MACHINE_NOT_WORKING )
-COMP( 1984, apricotxi, apricot, 0,      apricotxi, 0,     driver_device, 0,    "ACT",   "Apricot Xi", MACHINE_NOT_WORKING )
+COMP( 1983, apricot,   0,       0,      apricot,   0,     driver_device, 0,    "ACT",   "Apricot PC", 0 )
+COMP( 1984, apricotxi, apricot, 0,      apricotxi, 0,     driver_device, 0,    "ACT",   "Apricot Xi", 0 )
diff --git a/src/mame/drivers/arachnid.cpp b/src/mame/drivers/arachnid.cpp
index 0d6ad55..9256ff6 100644
--- a/src/mame/drivers/arachnid.cpp
+++ b/src/mame/drivers/arachnid.cpp
@@ -450,8 +450,7 @@ static MACHINE_CONFIG_START( arachnid, arachnid_state )
 	MCFG_SOUND_ADD("speaker", SPEAKER_SOUND, 0)
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
 
-	MCFG_DEVICE_ADD(PTM6840_TAG, PTM6840, 0)
-	MCFG_PTM6840_INTERNAL_CLOCK(XTAL_8MHz / 4)
+	MCFG_DEVICE_ADD(PTM6840_TAG, PTM6840, XTAL_8MHz / 4)
 	MCFG_PTM6840_EXTERNAL_CLOCKS(0, 0, 0)
 	MCFG_PTM6840_OUT0_CB(WRITELINE(arachnid_state, ptm_o1_callback))
 MACHINE_CONFIG_END
diff --git a/src/mame/drivers/aristmk5.cpp b/src/mame/drivers/aristmk5.cpp
index 2327d75..4b385c0 100644
--- a/src/mame/drivers/aristmk5.cpp
+++ b/src/mame/drivers/aristmk5.cpp
@@ -175,10 +175,14 @@
 #include "machine/ds1302.h"
 #include "machine/watchdog.h"
 #include "machine/eepromser.h"
+#include "machine/microtch.h"
+#include "machine/input_merger.h"
 #include "machine/nvram.h"
 #include "machine/ins8250.h"
 #include "sound/volt_reg.h"
 
+#include "aristmk5.lh"
+
 class aristmk5_state : public archimedes_state
 {
 public:
@@ -202,8 +206,12 @@ public:
 	DECLARE_READ32_MEMBER(eeprom_r);
 	DECLARE_READ32_MEMBER(ldor_r);
 	DECLARE_WRITE32_MEMBER(ldor_clk_w);
+	DECLARE_WRITE8_MEMBER(buttons_lamps_w);
+	DECLARE_WRITE8_MEMBER(other_lamps_w);
+	DECLARE_WRITE8_MEMBER(bill_acceptor_lamps_w);
 	DECLARE_READ8_MEMBER(sram_r);
 	DECLARE_WRITE8_MEMBER(sram_w);
+	DECLARE_WRITE_LINE_MEMBER(uart_irq_callback);
 
 	DECLARE_DRIVER_INIT(aristmk5);
 	virtual void machine_start() override;
@@ -231,6 +239,14 @@ private:
 };
 
 
+WRITE_LINE_MEMBER(aristmk5_state::uart_irq_callback)
+{
+	if (state)
+		archimedes_request_irq_b(0x20);
+	else
+		archimedes_clear_irq_b(0x20);
+}
+
 TIMER_CALLBACK_MEMBER(aristmk5_state::mk5_VSYNC_callback)
 {
 	m_ioc_regs[IRQ_STATUS_A] |= 0x08; //turn vsync bit on
@@ -499,6 +515,24 @@ WRITE32_MEMBER(aristmk5_state::sram_banksel_w)
 	m_sram_bank = ((data & 0xc0) >> 3) | (data & 0x07);
 }
 
+WRITE8_MEMBER(aristmk5_state::buttons_lamps_w)
+{
+	for(int i=0; i<8; i++)
+		output().set_lamp_value((offset >> 2) * 8 + i, BIT(data, i));
+}
+
+WRITE8_MEMBER(aristmk5_state::other_lamps_w)
+{
+	for(int i=0; i<8; i++)
+		output().set_lamp_value(16 + i, BIT(data, i));
+}
+
+WRITE8_MEMBER(aristmk5_state::bill_acceptor_lamps_w)
+{
+	for(int i=0; i<8; i++)
+		output().set_lamp_value(24 + i, BIT(data, i));
+}
+
 static ADDRESS_MAP_START( aristmk5_map, AS_PROGRAM, 32, aristmk5_state )
 	AM_RANGE(0x02000000, 0x02ffffff) AM_RAM AM_SHARE("physicalram") /* physical RAM - 16 MB for now, should be 512k for the A310 */
 
@@ -520,6 +554,10 @@ static ADDRESS_MAP_START( aristmk5_map, AS_PROGRAM, 32, aristmk5_state )
 	AM_RANGE(0x03012020, 0x03012023) AM_READ(ldor_r)
 	AM_RANGE(0x03012070, 0x03012073) AM_WRITE(ldor_clk_w)
 
+	AM_RANGE(0x03012000, 0x0301201f) AM_WRITE8(buttons_lamps_w, 0x000000ff)
+	AM_RANGE(0x03012030, 0x0301203f) AM_WRITE8(other_lamps_w, 0x000000ff)
+	AM_RANGE(0x03012380, 0x0301238f) AM_WRITE8(bill_acceptor_lamps_w, 0x000000ff)
+
 	AM_RANGE(0x03010480, 0x0301049f) AM_DEVREADWRITE8("uart_0a", ins8250_uart_device, ins8250_r, ins8250_w, 0x000000ff)
 	AM_RANGE(0x03010500, 0x0301051f) AM_DEVREADWRITE8("uart_0b", ins8250_uart_device, ins8250_r, ins8250_w, 0x000000ff)
 	AM_RANGE(0x03010600, 0x0301061f) AM_DEVREADWRITE8("uart_1a", ins8250_uart_device, ins8250_r, ins8250_w, 0x000000ff)
@@ -574,14 +612,14 @@ CUSTOM_INPUT_MEMBER(aristmk5_state::coin_r)
 	{
 		attotime diff = m_maincpu->cycles_to_attotime(m_maincpu->total_cycles() - m_coin_start_cycles);
 
-		if (diff > attotime::from_msec(40) && diff < attotime::from_msec(80))
+		if (diff > attotime::from_msec(5) && diff < attotime::from_msec(10))
 			data &= ~0x01;
-		if (diff > attotime::from_msec(120) && diff < attotime::from_msec(150))
+		if (diff > attotime::from_msec(15) && diff < attotime::from_msec(20))
 			data &= ~0x02;
-		if (diff <= attotime::from_msec(20))
+		if (diff <= attotime::from_msec(3))
 			data |= 0x08;
 
-		if (diff > attotime::from_msec(300))
+		if (diff > attotime::from_msec(30))
 			m_coin_start_cycles = 0;
 	}
 
@@ -876,15 +914,15 @@ static MACHINE_CONFIG_START( aristmk5, aristmk5_state )
 
 	// TL16C452FN U71
 	MCFG_DEVICE_ADD("uart_0a", NS16450, MASTER_CLOCK / 9)
-//  MCFG_INS8250_OUT_INT_CB(WRITELINE(aristmk5_state, uart_irq_callback))
+	MCFG_INS8250_OUT_INT_CB(DEVWRITELINE("uart_irq", input_merger_device, in0_w))
 	MCFG_DEVICE_ADD("uart_0b", NS16450, MASTER_CLOCK / 9)
-//  MCFG_INS8250_OUT_INT_CB(WRITELINE(aristmk5_state, uart_irq_callback))
+	MCFG_INS8250_OUT_INT_CB(DEVWRITELINE("uart_irq", input_merger_device, in1_w))
 
 	// TL16C452FN U72
 	MCFG_DEVICE_ADD("uart_1a", NS16450, MASTER_CLOCK / 9)
-//  MCFG_INS8250_OUT_INT_CB(WRITELINE(aristmk5_state, uart_irq_callback))
+	MCFG_INS8250_OUT_INT_CB(DEVWRITELINE("uart_irq", input_merger_device, in2_w))
 	MCFG_DEVICE_ADD("uart_1b", NS16450, MASTER_CLOCK / 9)
-//  MCFG_INS8250_OUT_INT_CB(WRITELINE(aristmk5_state, uart_irq_callback))
+	MCFG_INS8250_OUT_INT_CB(DEVWRITELINE("uart_irq", input_merger_device, in3_w))
 
 	// COMM port 4 - 5
 	MCFG_DEVICE_ADD("uart_2a", NS16450, MASTER_CLOCK / 9)
@@ -898,6 +936,9 @@ static MACHINE_CONFIG_START( aristmk5, aristmk5_state )
 	MCFG_DEVICE_ADD("uart_3b", NS16450, MASTER_CLOCK / 9)
 //  MCFG_INS8250_OUT_INT_CB(WRITELINE(aristmk5_state, uart_irq_callback))
 
+	MCFG_INPUT_MERGER_ACTIVE_HIGH("uart_irq")
+	MCFG_INPUT_MERGER_OUTPUT_HANDLER(WRITELINE(aristmk5_state, uart_irq_callback))
+
 	MCFG_DS1302_ADD("rtc", XTAL_32_768kHz)
 
 	MCFG_SPEAKER_STANDARD_MONO("speaker")
@@ -925,6 +966,13 @@ static MACHINE_CONFIG_DERIVED( aristmk5_usa, aristmk5 )
 	MCFG_CPU_PROGRAM_MAP(aristmk5_usa_map)
 MACHINE_CONFIG_END
 
+static MACHINE_CONFIG_DERIVED( aristmk5_usa_touch, aristmk5_usa )
+	MCFG_DEVICE_MODIFY("uart_0a")
+	MCFG_INS8250_OUT_TX_CB(DEVWRITELINE("microtouch", microtouch_device, rx))
+
+	MCFG_MICROTOUCH_ADD("microtouch", 2400, DEVWRITELINE("uart_0a", ins8250_uart_device, rx_w))
+MACHINE_CONFIG_END
+
 #define ARISTOCRAT_MK5_BIOS \
 	ROM_REGION( 0x400000, "set_4.04.09", ROMREGION_ERASEFF ) /* setchip v4.04.08 4meg */ \
 	ROM_LOAD32_WORD( "setchip v4.04.09.u7",  0x000000, 0x80000, CRC(e8e8dc75) SHA1(201fe95256459ce34fdb6f7498135ab5016d07f3) ) \
@@ -943,6 +991,22 @@ MACHINE_CONFIG_END
 	ROM_REGION16_BE( 0x100, "eeprom0", ROMREGION_ERASEFF ) \
 	ROM_REGION16_BE( 0x100, "eeprom1", ROMREGION_ERASEFF ) \
 
+#define ARISTOCRAT_MK5_BIOS_HAVE_EEPROMS \
+	ROM_REGION( 0x400000, "set_4.04.09", ROMREGION_ERASEFF ) /* setchip v4.04.08 4meg */ \
+	ROM_LOAD32_WORD( "setchip v4.04.09.u7",  0x000000, 0x80000, CRC(e8e8dc75) SHA1(201fe95256459ce34fdb6f7498135ab5016d07f3) ) \
+	ROM_LOAD32_WORD( "setchip v4.04.09.u11", 0x000002, 0x80000, CRC(ff7a9035) SHA1(4352c4336e61947c555fdc80c61f944076f64b64) ) \
+	ROM_REGION( 0x400000, "set_4.04.00", ROMREGION_ERASEFF ) /* setchip v4.04.00 4meg 42pin */ \
+	ROM_LOAD32_WORD( "setchip v4.04.00.u7",  0x000000, 0x80000, CRC(2453137e) SHA1(b59998e75ae3924da16faf47b9cfe9afd60d810c) ) \
+	ROM_LOAD32_WORD( "setchip v4.04.00.u11", 0x000002, 0x80000, CRC(82dfa12a) SHA1(86fd0f0ad8d5d1bc503392a40bbcdadb055b2765) ) \
+	ROM_REGION( 0x400000, "set_4.02.04", ROMREGION_ERASEFF ) /* setchip v4.02.04 */ \
+	ROM_LOAD32_WORD( "setchip v4.02.04.u7",  0x000000, 0x80000, CRC(5a254b22) SHA1(8444f237b392df2a3cb42ea349e7af32f47dd544) ) \
+	ROM_LOAD32_WORD( "setchip v4.02.04.u11", 0x000002, 0x80000, CRC(def36617) SHA1(c7ba5b08e884a8fb36c9fb51c08e243e32c81f89) ) \
+	/* GALs */ \
+	ROM_REGION( 0x600, "gals", 0 ) \
+	ROM_LOAD( "a562837.u36",  0x000000, 0x000157, CRC(1f269234) SHA1(29940dd50fb55c632935f62ff44ca724379c7a43) ) \
+	ROM_LOAD( "a562838.u65",  0x000200, 0x000157, CRC(f2f3c40a) SHA1(b795dfa5cc4e8127c3f3a0906664910d1325ec92) ) \
+	ROM_LOAD( "a562840.u22",  0x000400, 0x000157, CRC(941d4cdb) SHA1(1ca091fba69e92f262dbb3d40f515703c8981793) ) \
+
 
 ROM_START( aristmk5 )
 	ARISTOCRAT_MK5_BIOS
@@ -1497,23 +1561,16 @@ ROM_END
 // All devices are 27c4002 instead of 27c4096.
 ROM_START( chickna5u )
 	ARISTOCRAT_MK5_BIOS
-	/*
-	    Checksum code found at 0x000d08
-	    0x000000-0x0a6917 is the Checksummed Range (excluding 0x000020-0x000027 where Checksum is stored)
-	        Expected Checksum   0x0d44c6b0
-	        Calculated Checksum 0xc47bc6b0  (BAD)
-	    0x0a6918-0x35040b is the non-Checksummed range (unusual endpoint)
-	*/
+
 	ROM_REGION( 0x400000, "game_prg", ROMREGION_ERASEFF )
-	// the checksum only covers part of the first 2 roms, marked all as BAD_DUMP because it can't be trusted without a full redump.
-	ROM_LOAD32_WORD( "rhg073003.u7",  0x000000, 0x80000, BAD_DUMP CRC(ca196b37) SHA1(6b204204c1574439ccea1b6145d867a73bad304f) )  // 92.588%
-	ROM_LOAD32_WORD( "rhg073003.u11", 0x000002, 0x80000, BAD_DUMP CRC(b0d7be28) SHA1(6998dce808bf7970500b9e1ce6efed3940ee2d63) )  // 92.588%
-	ROM_LOAD32_WORD( "rhg073003.u8",  0x100000, 0x80000, BAD_DUMP CRC(80e3e34c) SHA1(3ad73c5fc21c4d9647ea514bf367073bbeb981a9) )  // base
-	ROM_LOAD32_WORD( "rhg073003.u12", 0x100002, 0x80000, BAD_DUMP CRC(63d5ec8e) SHA1(dca76342ecee6843e6fc656aafc8ee2e4d19fd65) )  // base
-	ROM_LOAD32_WORD( "rhg073003.u9",  0x200000, 0x80000, BAD_DUMP CRC(662ff210) SHA1(bbd2410fa2cd67e327981c3b2e16342fb9393401) )  // base
-	ROM_LOAD32_WORD( "rhg073003.u13", 0x200002, 0x80000, BAD_DUMP CRC(c3cef8ae) SHA1(4e65787d61387b511972e514047528495e1de11c) )  // base
-	ROM_LOAD32_WORD( "rhg073003.u10", 0x300000, 0x80000, BAD_DUMP CRC(8b3f7d6b) SHA1(7f1a04556c448976145652b05b690142376764d4) )  // base
-	ROM_LOAD32_WORD( "rhg073003.u14", 0x300002, 0x80000, BAD_DUMP CRC(240f7759) SHA1(1fa5ba0185b027101dae207ec5d28b07d3d73fc2) )  // base
+	ROM_LOAD32_WORD( "rhg073003.u7",  0x000000, 0x080000, CRC(06558129) SHA1(be726c0d35776faf1ecd20eb0a193e68a1fb1a84) )
+	ROM_LOAD32_WORD( "rhg073003.u11", 0x000002, 0x080000, CRC(0eadf5d4) SHA1(b783f6e1911fc098d1b4d1d8c75862e031078e5b) )
+	ROM_LOAD32_WORD( "rhg073003.u8",  0x100000, 0x080000, CRC(683e96bc) SHA1(bca8e87bea9f7044fa29dc4518e2ac5b429e3313) )
+	ROM_LOAD32_WORD( "rhg073003.u12", 0x100002, 0x080000, CRC(8313b03b) SHA1(d2a91bae8063d89ec9a1edab6df3e6711719d2c2) )
+	ROM_LOAD32_WORD( "rhg073003.u9",  0x200000, 0x080000, CRC(9c08aefa) SHA1(fe3ffa8eb308ab216cc08dd2ce51113b4ef74c4a) )
+	ROM_LOAD32_WORD( "rhg073003.u13", 0x200002, 0x080000, CRC(69fd4f89) SHA1(4e0469caecf9293197a4a5de960eb9dcfee39ca3) )
+	ROM_LOAD32_WORD( "rhg073003.u10", 0x300000, 0x080000, CRC(9aae49d7) SHA1(5cf87b747ea7561766fe0ffc15967fea657b252b) )
+	ROM_LOAD32_WORD( "rhg073003.u14", 0x300002, 0x080000, CRC(240f7759) SHA1(1fa5ba0185b027101dae207ec5d28b07d3d73fc2) )
 
 	ROM_REGION( 0x800000, "maincpu", ROMREGION_ERASE00 ) /* ARM Code */
 	ROM_REGION( 0x200000, "vram", ROMREGION_ERASE00 )
@@ -1594,7 +1651,7 @@ ROM_END
 // CUCKOO - Export C - 02/02/00.
 // All devices are 27c4002 instead of 27c4096.
 ROM_START( cuckoou )
-	ARISTOCRAT_MK5_BIOS
+	ARISTOCRAT_MK5_BIOS_HAVE_EEPROMS
 	/*
 	    Checksum code found at 0x000d18
 	    0x000000-0x0a588b is the Checksummed Range (excluding 0x000020-0x000027 where Checksum is stored)
@@ -1612,6 +1669,19 @@ ROM_START( cuckoou )
 	ROM_REGION( 0x800000, "maincpu", ROMREGION_ERASE00 ) /* ARM Code */
 	ROM_REGION( 0x200000, "vram", ROMREGION_ERASE00 )
 	ROM_REGION( 0x20000*4, "sram", ROMREGION_ERASE00 )
+
+	ROM_REGION16_BE( 0x100, "eeprom0", 0 )
+	ROM_LOAD16_WORD_SWAP( "eeprom0",      0x000000, 0x000100, CRC(fea8a821) SHA1(c744cac6af7621524fc3a2b0a9a135a32b33c81b) )
+
+	ROM_REGION16_BE( 0x100, "eeprom1", 0 )
+	ROM_LOAD16_WORD_SWAP( "eeprom1",      0x000000, 0x000100, CRC(415b9c77) SHA1(86a3b3aabd81f5fcf767dd53f7034f7d58f2020e) )
+
+	ROM_REGION( 0x80000, "nvram", 0 )
+	ROM_LOAD( "nvram",        0x000000, 0x080000, CRC(64c895fe) SHA1(12c75338dd1b2260d0581744cef1b705c718727f) )
+
+	ROM_REGION( 0x20, "rtc", 0 )
+	ROM_LOAD( "rtc",          0x000000, 0x00001f, CRC(6909acb0) SHA1(6a4589599cd1c477e916474e7b029e9a4e92019b) )
+
 ROM_END
 
 
@@ -1760,7 +1830,7 @@ ROM_END
 // Dolphin Treasure - Export B - 06/12/96.
 // All devices are 27c4002 instead of 27c4096.
 ROM_START( dolphntru )
-	ARISTOCRAT_MK5_BIOS
+	ARISTOCRAT_MK5_BIOS_HAVE_EEPROMS
 	/*
 	    Checksum code found at 0x000d08
 	    0x000000-0x08ec8b is the Checksummed Range (excluding 0x000020-0x000027 where Checksum is stored)
@@ -1778,6 +1848,18 @@ ROM_START( dolphntru )
 	ROM_REGION( 0x800000, "maincpu", ROMREGION_ERASE00 ) /* ARM Code */
 	ROM_REGION( 0x200000, "vram", ROMREGION_ERASE00 )
 	ROM_REGION( 0x20000*4, "sram", ROMREGION_ERASE00 )
+
+	ROM_REGION16_BE( 0x100, "eeprom0", 0 )
+	ROM_LOAD16_WORD_SWAP( "eeprom0",      0x000000, 0x000100, CRC(fea8a821) SHA1(c744cac6af7621524fc3a2b0a9a135a32b33c81b) )
+
+	ROM_REGION16_BE( 0x100, "eeprom1", 0 )
+	ROM_LOAD16_WORD_SWAP( "eeprom1",      0x000000, 0x000100, CRC(1fc27753) SHA1(7e5008faaf115dc506481430272285117c989d8e) )
+
+	ROM_REGION( 0x80000, "nvram", 0 )
+	ROM_LOAD( "nvram",        0x000000, 0x080000, CRC(0063e5ca) SHA1(a3d7b636bc9d792e93d11cb2babf24fbdd6d7776) )
+
+	ROM_REGION( 0x20, "rtc", 0 )
+	ROM_LOAD( "rtc",          0x000000, 0x00001f, CRC(6909acb0) SHA1(6a4589599cd1c477e916474e7b029e9a4e92019b) )
 ROM_END
 
 
@@ -2079,7 +2161,7 @@ ROM_START( incasun )
 ROM_END
 
 ROM_START( incasunu )
-	ARISTOCRAT_MK5_BIOS
+	ARISTOCRAT_MK5_BIOS_HAVE_EEPROMS
 
 	ROM_REGION( 0x400000, "game_prg", ROMREGION_ERASEFF )
 	ROM_LOAD32_WORD("chg1458.u7",  0x0000000, 0x0080000, CRC(20c78b79) SHA1(d7402ff89160f25c9f4f67bbf688621d4ce22205) )
@@ -2092,6 +2174,18 @@ ROM_START( incasunu )
 	ROM_REGION( 0x800000, "maincpu", ROMREGION_ERASE00 ) /* ARM Code */
 	ROM_REGION( 0x200000, "vram", ROMREGION_ERASE00 )
 	ROM_REGION( 0x20000*4, "sram", ROMREGION_ERASE00 )
+
+	ROM_REGION16_BE( 0x100, "eeprom0", 0 )
+	ROM_LOAD16_WORD_SWAP( "eeprom0",      0x000000, 0x000100, CRC(fea8a821) SHA1(c744cac6af7621524fc3a2b0a9a135a32b33c81b) )
+
+	ROM_REGION16_BE( 0x100, "eeprom1", 0 )
+	ROM_LOAD16_WORD_SWAP( "eeprom1",      0x000000, 0x000100, CRC(b3efdb60) SHA1(f219175019b7237f1e2d132f36803097f2a1d174) )
+
+	ROM_REGION( 0x80000, "nvram", 0 )
+	ROM_LOAD( "nvram",        0x000000, 0x080000, CRC(a68e890e) SHA1(8ab087a09cfee8d3e2d84b1003b6798c7223be03) )
+
+	ROM_REGION( 0x20, "rtc", 0 )
+	ROM_LOAD( "rtc",          0x000000, 0x00001f, CRC(6909acb0) SHA1(6a4589599cd1c477e916474e7b029e9a4e92019b) )
 ROM_END
 
 ROM_START( incasunsp )
@@ -2337,7 +2431,7 @@ ROM_END
 // MV4115 - 5,10,20 Credit Multiplier / 9 Line Multiline.
 // Magic Mask [Reel Game] - Export A - 09/05/2000.
 ROM_START( magimask )
-	ARISTOCRAT_MK5_BIOS
+	ARISTOCRAT_MK5_BIOS_HAVE_EEPROMS
 	/*
 	    Checksum code found at 0x000d18
 	    0x000000-0x0e8527 is the Checksummed Range (excluding 0x000020-0x000027 where Checksum is stored)
@@ -2355,6 +2449,18 @@ ROM_START( magimask )
 	ROM_REGION( 0x800000, "maincpu", ROMREGION_ERASE00 ) /* ARM Code */
 	ROM_REGION( 0x200000, "vram", ROMREGION_ERASE00 )
 	ROM_REGION( 0x20000*4, "sram", ROMREGION_ERASE00 )
+
+	ROM_REGION16_BE( 0x100, "eeprom0", 0 )
+	ROM_LOAD16_WORD_SWAP( "eeprom0",      0x000000, 0x000100, CRC(fea8a821) SHA1(c744cac6af7621524fc3a2b0a9a135a32b33c81b) )
+
+	ROM_REGION16_BE( 0x100, "eeprom1", 0 )
+	ROM_LOAD16_WORD_SWAP( "eeprom1",      0x000000, 0x000100, CRC(6e485bbc) SHA1(3d6c8d120c69ed2804f267c50681974f73e1ee51) )
+
+	ROM_REGION( 0x80000, "nvram", 0 )
+	ROM_LOAD( "nvram",        0x000000, 0x080000, CRC(538c7523) SHA1(1e6516b77daf855e397c1ec590e73637ce3b8406) )
+
+	ROM_REGION( 0x20, "rtc", 0 )
+	ROM_LOAD( "rtc",          0x000000, 0x00001f, CRC(6909acb0) SHA1(6a4589599cd1c477e916474e7b029e9a4e92019b) )
 ROM_END
 
 
@@ -2370,7 +2476,7 @@ ROM_END
 // dhg1309.u11    ahg1548.u11    17.786026%
 // dhg1309.u7     ahg1548.u7     16.893578%
 ROM_START( magimaska )
-	ARISTOCRAT_MK5_BIOS
+	ARISTOCRAT_MK5_BIOS_HAVE_EEPROMS
 	/*
 	    Checksum code found at 0x000d18
 	    0x000000-0x0e9597 is the Checksummed Range (excluding 0x000020-0x000027 where Checksum is stored)
@@ -2388,6 +2494,18 @@ ROM_START( magimaska )
 	ROM_REGION( 0x800000, "maincpu", ROMREGION_ERASE00 ) /* ARM Code */
 	ROM_REGION( 0x200000, "vram", ROMREGION_ERASE00 )
 	ROM_REGION( 0x20000*4, "sram", ROMREGION_ERASE00 )
+
+	ROM_REGION16_BE( 0x100, "eeprom0", 0 )
+	ROM_LOAD16_WORD_SWAP( "eeprom0",      0x000000, 0x000100, CRC(fea8a821) SHA1(c744cac6af7621524fc3a2b0a9a135a32b33c81b) )
+
+	ROM_REGION16_BE( 0x100, "eeprom1", 0 )
+	ROM_LOAD16_WORD_SWAP( "eeprom1",      0x000000, 0x000100, CRC(a10501f9) SHA1(34fdcd16bd7dc474baadc0836e2083abaf589549) )
+
+	ROM_REGION( 0x80000, "nvram", 0 )
+	ROM_LOAD( "nvram",       0x000000, 0x080000, CRC(5365446b) SHA1(9ae7a72d0ed3e7f7523a2e0a8f0dc014c6490438) )
+
+	ROM_REGION( 0x20, "rtc", 0 )
+	ROM_LOAD( "rtc",          0x000000, 0x00001f, CRC(6909acb0) SHA1(6a4589599cd1c477e916474e7b029e9a4e92019b) )
 ROM_END
 
 
@@ -2466,7 +2584,7 @@ ROM_END
 // Mine, Mine, Mine - Export E - 14/02/96.
 // All devices are 27c4002 instead of 27c4096.
 ROM_START( minemine )
-	ARISTOCRAT_MK5_BIOS
+	ARISTOCRAT_MK5_BIOS_HAVE_EEPROMS
 	/*
 	    Checksum code found at 0x000d10
 	    0x000000-0x0a7203 is the Checksummed Range (excluding 0x000020-0x000027 where Checksum is stored)
@@ -2484,6 +2602,18 @@ ROM_START( minemine )
 	ROM_REGION( 0x800000, "maincpu", ROMREGION_ERASE00 ) /* ARM Code */
 	ROM_REGION( 0x200000, "vram", ROMREGION_ERASE00 )
 	ROM_REGION( 0x20000*4, "sram", ROMREGION_ERASE00 )
+
+	ROM_REGION16_BE( 0x100, "eeprom0", 0 )
+	ROM_LOAD16_WORD_SWAP( "eeprom0",      0x000000, 0x000100, CRC(fea8a821) SHA1(c744cac6af7621524fc3a2b0a9a135a32b33c81b) )
+
+	ROM_REGION16_BE( 0x100, "eeprom1", 0 )
+	ROM_LOAD16_WORD_SWAP( "eeprom1",      0x000000, 0x000100, CRC(8421e7c2) SHA1(fc1b07d5b7aadafc4a0f2e4dfa698e7c72340717) )
+
+	ROM_REGION( 0x80000, "nvram", 0 )
+	ROM_LOAD( "nvram",        0x000000, 0x080000, CRC(883f5023) SHA1(e526e337b5b0fc77091b4946b503b56307c390e9) )
+
+	ROM_REGION( 0x20, "rtc", 0 )
+	ROM_LOAD( "rtc",          0x000000, 0x00001f, CRC(6909acb0) SHA1(6a4589599cd1c477e916474e7b029e9a4e92019b) )
 ROM_END
 
 
@@ -2656,7 +2786,7 @@ ROM_END
 // Party Gras [Reel Game] - Export A - 10/11/2001.
 // All devices are 27c4002 instead of 27c4096.
 ROM_START( partygrs )
-	ARISTOCRAT_MK5_BIOS
+	ARISTOCRAT_MK5_BIOS_HAVE_EEPROMS
 	/*
 	    Checksum code found at 0x000d18
 	    0x000000-0x0e9b47 is the Checksummed Range (excluding 0x000020-0x000027 where Checksum is stored)
@@ -2674,6 +2804,18 @@ ROM_START( partygrs )
 	ROM_REGION( 0x800000, "maincpu", ROMREGION_ERASE00 ) /* ARM Code */
 	ROM_REGION( 0x200000, "vram", ROMREGION_ERASE00 )
 	ROM_REGION( 0x20000*4, "sram", ROMREGION_ERASE00 )
+
+	ROM_REGION16_BE( 0x100, "eeprom0", 0 )
+	ROM_LOAD16_WORD_SWAP( "eeprom0",      0x000000, 0x000100, CRC(fea8a821) SHA1(c744cac6af7621524fc3a2b0a9a135a32b33c81b) )
+
+	ROM_REGION16_BE( 0x100, "eeprom1", 0 )
+	ROM_LOAD16_WORD_SWAP( "eeprom1",      0x000000, 0x000100, CRC(a10501f9) SHA1(34fdcd16bd7dc474baadc0836e2083abaf589549) )
+
+	ROM_REGION( 0x80000, "nvram", 0 )
+	ROM_LOAD( "nvram",        0x000000, 0x080000, CRC(fec1b1df) SHA1(5981e2961692d4c8633afea4ecb4828eabba65bd) )
+
+	ROM_REGION( 0x20, "rtc", 0 )
+	ROM_LOAD( "rtc",          0x000000, 0x00001f, CRC(6909acb0) SHA1(6a4589599cd1c477e916474e7b029e9a4e92019b) )
 ROM_END
 
 
@@ -2795,7 +2937,7 @@ ROM_END
 // Penguin Pays - Export B - 14/07/97.
 // All devices are 27c4002 instead of 27c4096.
 ROM_START( pengpayu )
-	ARISTOCRAT_MK5_BIOS
+	ARISTOCRAT_MK5_BIOS_HAVE_EEPROMS
 	/*
 	    Checksum code found at 0x000d08
 	    0x000000-0x0cd21b is the Checksummed Range (excluding 0x000020-0x000027 where Checksum is stored)
@@ -2813,6 +2955,18 @@ ROM_START( pengpayu )
 	ROM_REGION( 0x800000, "maincpu", ROMREGION_ERASE00 ) /* ARM Code */
 	ROM_REGION( 0x200000, "vram", ROMREGION_ERASE00 )
 	ROM_REGION( 0x20000*4, "sram", ROMREGION_ERASE00 )
+
+	ROM_REGION16_BE( 0x100, "eeprom0", 0 )
+	ROM_LOAD16_WORD_SWAP( "eeprom0",      0x000000, 0x000100, CRC(fea8a821) SHA1(c744cac6af7621524fc3a2b0a9a135a32b33c81b) )
+
+	ROM_REGION16_BE( 0x100, "eeprom1", 0 )
+	ROM_LOAD16_WORD_SWAP( "eeprom1",      0x000000, 0x000100, CRC(8421e7c2) SHA1(fc1b07d5b7aadafc4a0f2e4dfa698e7c72340717) )
+
+	ROM_REGION( 0x80000, "nvram", 0 )
+	ROM_LOAD( "nvram",        0x000000, 0x080000, CRC(4e5b9702) SHA1(b2b645db80c4ece24fae8ce6fb660e77ac8e5810) )
+
+	ROM_REGION( 0x20, "rtc", 0 )
+	ROM_LOAD( "rtc",          0x000000, 0x00001f, CRC(6909acb0) SHA1(6a4589599cd1c477e916474e7b029e9a4e92019b) )
 ROM_END
 
 
@@ -2972,7 +3126,7 @@ ROM_END
 // All devices are 27c4002 instead of 27c4096.
 // Even when it's a NSW/ACT, the program seems to be for US-Export platforms...
 ROM_START( qnileu )
-	ARISTOCRAT_MK5_BIOS
+	ARISTOCRAT_MK5_BIOS_HAVE_EEPROMS
 	/*
 	    Checksum code found at 0x000d08
 	    0x000000-0x08ec87 is the Checksummed Range (excluding 0x000020-0x000027 where Checksum is stored)
@@ -2990,6 +3144,18 @@ ROM_START( qnileu )
 	ROM_REGION( 0x800000, "maincpu", ROMREGION_ERASE00 ) /* ARM Code */
 	ROM_REGION( 0x200000, "vram", ROMREGION_ERASE00 )
 	ROM_REGION( 0x20000*4, "sram", ROMREGION_ERASE00 )
+
+	ROM_REGION16_BE( 0x100, "eeprom0", 0 )
+	ROM_LOAD16_WORD_SWAP( "eeprom0",      0x000000, 0x000100, CRC(fea8a821) SHA1(c744cac6af7621524fc3a2b0a9a135a32b33c81b) )
+
+	ROM_REGION16_BE( 0x100, "eeprom1", 0 )
+	ROM_LOAD16_WORD_SWAP( "eeprom1",      0x000000, 0x000100, CRC(1fc27753) SHA1(7e5008faaf115dc506481430272285117c989d8e) )
+
+	ROM_REGION( 0x80000, "nvram", 0 )
+	ROM_LOAD( "nvram",        0x000000, 0x080000, CRC(5a7bb53a) SHA1(cdac900925d0ee8f98209a377b9f8760de0c2883) )
+
+	ROM_REGION( 0x20, "rtc", 0 )
+	ROM_LOAD( "rtc",          0x000000, 0x00001f, CRC(6909acb0) SHA1(6a4589599cd1c477e916474e7b029e9a4e92019b) )
 ROM_END
 
 
@@ -3261,10 +3427,9 @@ ROM_END
 
 ROM_START( topbana )
 	ARISTOCRAT_MK5_BIOS
-	// checksum code not found (due to bad rom)
 	ROM_REGION( 0x400000, "game_prg", ROMREGION_ERASEFF )
-	ROM_LOAD32_WORD("0100550v.u7",  0x0000000, 0x0080000, CRC(1f60241c) SHA1(3a6207d9c919319fc10b6de63bc030f8d335588e) )
-	ROM_LOAD32_WORD("0100550v.u11", 0x0000002, 0x007fffa, BAD_DUMP CRC(140a73bc) SHA1(3fd88797b6310f5849e901d032fbeb8a2d8604fb) )   // This is a bad .u8 from Indian Dream, not proper Top Banana .u11!!
+	ROM_LOAD32_WORD( "0100550v.u11", 0x000002, 0x080000, CRC(1c64b3b6) SHA1(80bbc6e3f47ab932e9c07e0c6063197a2d8e81f7) )
+	ROM_LOAD32_WORD( "0100550v.u7",  0x000000, 0x080000, CRC(9c5e2d66) SHA1(658143706c0e1f3b43b3ec301da1052363fe5244) )
 
 	ROM_REGION( 0x800000, "maincpu", ROMREGION_ERASE00 ) /* ARM Code */
 	ROM_REGION( 0x200000, "vram", ROMREGION_ERASE00 )
@@ -3513,7 +3678,7 @@ ROM_END
 // Wild Cougar - Export D - 19/05/97.
 // All devices are 27c4002 instead of 27c4096.
 ROM_START( wcougaru )
-	ARISTOCRAT_MK5_BIOS
+	ARISTOCRAT_MK5_BIOS_HAVE_EEPROMS
 	/*
 	    Checksum code found at 0x000d08
 	    0x000000-0x0b0d5b is the Checksummed Range (excluding 0x000020-0x000027 where Checksum is stored)
@@ -3531,6 +3696,18 @@ ROM_START( wcougaru )
 	ROM_REGION( 0x800000, "maincpu", ROMREGION_ERASE00 ) /* ARM Code */
 	ROM_REGION( 0x200000, "vram", ROMREGION_ERASE00 )
 	ROM_REGION( 0x20000*4, "sram", ROMREGION_ERASE00 )
+
+	ROM_REGION16_BE( 0x100, "eeprom0", 0 )
+	ROM_LOAD16_WORD_SWAP( "eeprom0",      0x000000, 0x000100, CRC(fea8a821) SHA1(c744cac6af7621524fc3a2b0a9a135a32b33c81b) )
+
+	ROM_REGION16_BE( 0x100, "eeprom1", 0 )
+	ROM_LOAD16_WORD_SWAP( "eeprom1",      0x000000, 0x000100, CRC(8421e7c2) SHA1(fc1b07d5b7aadafc4a0f2e4dfa698e7c72340717) )
+
+	ROM_REGION( 0x80000, "nvram", 0 )
+	ROM_LOAD( "nvram",        0x000000, 0x080000, CRC(dfe52286) SHA1(db31fb64e2fff8aa5ba0cc6d3d73860e8019406c) )
+
+	ROM_REGION( 0x20, "rtc", 0 )
+	ROM_LOAD( "rtc",          0x000000, 0x00001f, CRC(6909acb0) SHA1(6a4589599cd1c477e916474e7b029e9a4e92019b) )
 ROM_END
 
 
@@ -3587,120 +3764,120 @@ ROM_END
 GAME( 1995, aristmk5,  0,        aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "MKV Set/Clear Chips (USA)",                    MACHINE_FLAGS|MACHINE_IS_BIOS_ROOT )
 
 // Dates listed below are for the combination (reel layout), not release dates
-GAME( 1998, adonis,    aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Adonis (0200751V, NSW/ACT)",                   MACHINE_FLAGS )  // 602/9,    A - 25/05/98, Rev 10
-GAME( 1998, adonisa,   adonis,   aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Adonis (0100751V, NSW/ACT)",                   MACHINE_FLAGS )  // 602/9,    A - 25/05/98, Rev 9
-GAME( 2001, adonisu,   adonis,   aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Adonis (BHG1508, US)",                         MACHINE_FLAGS )  // MV4124/1, B - 31/07/01 - BAD DUMP
-GAME( 1999, adonisce,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Adonis - Cash Express (0201005V, NSW/ACT)",    MACHINE_FLAGS )  // 602/9, C - 06/07/99
-GAME( 1996, baddog,    aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Bad Dog Poker (0200428V, NSW/ACT)",            MACHINE_FLAGS )  // 386/56, A - 17/12/96
-GAME( 1996, blackpnt,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Black Panther (0200818V, Victoria)",           MACHINE_FLAGS )  // 594/1, A - 30/07/96
-GAME( 1998, bootsctn,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Boot Scootin' (0100812V, NSW/ACT)",            MACHINE_FLAGS )  // 616/1, B - 11/12/98
-GAME( 1999, bootsctnu, bootsctn, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Boot Scootin' (GHG1012-02, US)",               MACHINE_FLAGS )  // MV4098,   A - 25/08/99 - BAD DUMP
-GAME( 1996, bumblbug,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Bumble Bugs (0200510V, NSW/ACT)",              MACHINE_FLAGS )  // 593, D - 5/07/96
-GAME( 1996, bumblbugql,bumblbug, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Bumble Bugs (0200456V, Queensland)",           MACHINE_FLAGS )  // 593,      D - 5/07/96
-GAME( 1997, bumblbugu, bumblbug, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Bumble Bugs (CHG0479-03, US)",                 MACHINE_FLAGS )  // 593,      D - 05/07/97 - BAD DUMP
-GAME( 1995, buttdeli,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Butterfly Delight (0200143V, NSW/ACT)",        MACHINE_FLAGS )  // 571/4, A - 19/12/95
-GAME( 1999, cashcat,   aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Cash Cat (0300863V, New Zealand)",             MACHINE_FLAGS )  // MV4089, A - 4/1/99
-GAME( 1997, cashcham,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Cash Chameleon (0100438V, NSW/ACT)",           MACHINE_FLAGS )  // 603/1, C  - 15/4/97
-GAME( 1996, cashchamu, cashcham, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Cash Chameleon (DHG4078-99, US)",              MACHINE_FLAGS )  // 603(a),   B - 06/12/96 - BAD DUMP
-GAME( 1998, cashchama, cashcham, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Cash Chameleon (0200437V, NSW/ACT)",           MACHINE_FLAGS )  // 603(a), D - 18/02/98
-GAME( 1998, cashchamnz,cashcham, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Cash Chameleon (0300781V, New Zealand)",       MACHINE_FLAGS )  // MV4067, A - 31/08/98
-GAME( 1997, cashcra5,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Cash Crop (0300467V, NSW/ACT)",                MACHINE_FLAGS )  // 607, C - 14/07/97
-GAME( 1998, chariotc,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "The Chariot Challenge (04J00714, NSW/ACT)",    MACHINE_FLAGS )  // 630,      A - 10/08/98, Rev 12
-GAME( 1998, chariotca, chariotc, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "The Chariot Challenge (0100787V, NSW/ACT)",    MACHINE_FLAGS )  // 630/1, A - 10/08/98
-GAME( 2001, checkma5,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Checkmate (01J00681, NSW/ACT)",                MACHINE_FLAGS )  // JB011, B - 06/07/01
-GAME( 1996, chickna5,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Chicken (0100351V, NSW/ACT)",                  MACHINE_FLAGS )  // 596, A - 27/08/96
-GAME( 1998, chickna5u, chickna5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Chicken (RHG0730-03, US)",                     MACHINE_FLAGS )  // 596,      C - 23/02/98 - BAD DUMP
-GAME( 1998, chickna5qld,chickna5,aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Chicken (0200530V, Queensland)",               MACHINE_FLAGS )  // 596, C - 23/02/98
-GAME( 1998, coralrc2,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Coral Riches II (0100919V, NSW/ACT)",          MACHINE_FLAGS )  // 577/7, A - 29/12/98
-GAME( 1998, cuckoo,    aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Cuckoo (0200753V, NSW/ACT)",                   MACHINE_FLAGS )  // 615/1, D - 03/07/98
-GAME( 2000, cuckoou,   cuckoo,   aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Cuckoo (CHG1195, US)",                         MACHINE_FLAGS )  // MV4104,   C - 02/02/00
-GAME( 1995, dstbloom,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Desert Bloom (0200111V, NSW/ACT)",             MACHINE_FLAGS )  // 577/2, A - 12/10/95
-GAME( 1999, diamdove,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Diamond Dove (0101018V, NSW/ACT)",             MACHINE_FLAGS )  // 640, B - 19/05/99
-GAME( 1996, dmdfever,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Diamond Fever (0200302V, NSW/ACT)",            MACHINE_FLAGS )  // 483/7, E - 05/09/96
-GAME( 1997, dimtouch,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Diamond Touch (0400433V, NSW/ACT)",            MACHINE_FLAGS )  // 604,      E - 30/06/97
-GAME( 1996, dolphntr,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Dolphin Treasure (0200424V, NSW/ACT)",         MACHINE_FLAGS )  // 602/1,    B - 06/12/96, Rev 3
-GAME( 1996, dolphntra, dolphntr, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Dolphin Treasure (0100424V, NSW/ACT)",         MACHINE_FLAGS )  // 602/1,    B - 06/12/96, Rev 1.24.4.0
-GAME( 1996, dolphntrb, dolphntr, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Dolphin Treasure (0100388V, NSW/ACT)",         MACHINE_FLAGS )  // 602, B - 10/12/96
-GAME( 1996, dolphntru, dolphntr, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Dolphin Treasure (FHG4077-02, US)",            MACHINE_FLAGS )  // 602/1,    B - 06/12/96
-GAME( 2000, dynajack,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Dynamite Jack (01J00081, NSW/ACT)",            MACHINE_FLAGS )  // JB004, A - 12/07/2000
-GAME( 1998, eldorda5,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "El Dorado (0100652V, NSW/ACT)",                MACHINE_FLAGS )  // 623, B - 24/03/98
-GAME( 1995, eforsta5,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Enchanted Forest (0400122V, NSW/ACT)",         MACHINE_FLAGS )  // 570/3,    E - 23/06/95
-GAME( 1997, eforsta5u, eforsta5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Enchanted Forest (JHG0415-03, US)",            MACHINE_FLAGS )  // MV4033,   B - 10/02/97
-GAME( 2000, fortellr,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Fortune Teller (01J00131, NSW/ACT)",           MACHINE_FLAGS )  // JB006, D - 24/11/2000
-GAME( 1998, gambler,   aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "The Gambler (EHG0916-02, US)",                 MACHINE_FLAGS )  // MV4084/1, A - 30/10/98 - POSSIBLE BAD DUMP
-GAME( 2001, geisha,    aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Geisha (0101408V, New Zealand)",               MACHINE_FLAGS )  // MV4127,   A - 05/03/01
-GAME( 1999, genmagi,   aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Genie Magic (0200894V, NSW/ACT)",              MACHINE_FLAGS )  // ???,   C - 15/02/99
-GAME( 1998, gnomeatw,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Gnome Around The World (0100767V, NSW/ACT)",   MACHINE_FLAGS )  // 625, C - 18/12/98
-GAME( 1997, goldpyr,   aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Golden Pyramids (AHG1205-03, US)",             MACHINE_FLAGS )  // MV4091,   B - 13/05/97
-GAME( 1997, goldpyra,  goldpyr,  aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Golden Pyramids (AHG1206-99, US)",             MACHINE_FLAGS )  // 602/2,    B - 13/05/97 - BAD DUMP
-GAME( 2000, goldenra,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Golden Ra (0101164V, NSW/ACT)",                MACHINE_FLAGS )  // 661, A - 10/04/00
-GAME( 1999, incasun,   aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Inca Sun (0100872V, NSW/ACT)",                 MACHINE_FLAGS )  // 631/3 B, B - 03/05/99
-GAME( 1999, incasunsp, incasun,  aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Inca Sun (0100872V, NSW/ACT, Show Program)",   MACHINE_FLAGS )  // 631/3 B, B - 03/05/99
-GAME( 2000, incasunnz, incasun,  aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Inca Sun (0101108V, New Zealand)",             MACHINE_FLAGS )  // MV4113, A - 6/3/00
-GAME( 2000, incasunu,  incasun,  aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Inca Sun (CHG1458, US)",                       MACHINE_FLAGS )  // MV4130/3, A - 05/09/00
-GAME( 1998, indrema5,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Indian Dreaming (0100845V, NSW/ACT)",          MACHINE_FLAGS )  // 628/1,    B - 15/12/98
-GAME( 1996, jungjuic,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Jungle Juice (0200240V, New Zealand)",         MACHINE_FLAGS )  // 566/3, F - 06/03/96
-GAME( 1995, kgalah,    aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "King Galah (0200536V, NSW/ACT)",               MACHINE_FLAGS )  // 613/6, A - 21/07/95
-GAME( 2001, koalamnt,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Koala Mint (CHG1573, US)",                     MACHINE_FLAGS )  // MV4137,   A - 12/09/01 - BAD DUMP
-GAME( 1998, kookabuk,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Kooka Bucks (0100677V, NSW/ACT)",              MACHINE_FLAGS )  // 661, A - 03/04/98
-GAME( 1997, locoloot,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Loco Loot (0100472V, NSW/ACT)",                MACHINE_FLAGS )  // 599/2, C - 17/06/97
-GAME( 1998, locolootnz,locoloot, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Loco Loot (0600725V, New Zealand)",            MACHINE_FLAGS )  // MV4064, A - 8/7/98
-GAME( 1997, lonewolf,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Lone Wolf (0100587V, NSW/ACT)",                MACHINE_FLAGS )  // 621, A - 29/10/97
-GAME( 1997, mgarden,   aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Magic Garden (AHG1211-99, US)",                MACHINE_FLAGS )  // MV4033,   B - 10/02/97 - BAD DUMP
-GAME( 2000, magimask,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Magic Mask (DHG1309, US)",                     MACHINE_FLAGS )  // MV4115,   A - 09/05/00
-GAME( 2000, magimaska, magimask, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Magic Mask (AHG1548, US)",                     MACHINE_FLAGS )  // MV4115,   A - 09/05/00
-GAME( 1997, magtcha5,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Magic Touch (0200455V, NSW/ACT)",              MACHINE_FLAGS )  // 606, A - 06/03/97
-GAME( 2000, marmagic,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Margarita Magic (01J00101, NSW/ACT)",          MACHINE_FLAGS )  // JB005,    A - 07/07/00
-GAME( 2000, marmagicu, marmagic, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Margarita Magic (EHG1559, US)",                MACHINE_FLAGS )  // US003,    A - 07/07/00 - BAD DUMP
-GAME( 1996, minemine,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Mine, Mine, Mine (VHG0416-99, US)",            MACHINE_FLAGS )  // 559/2,    E - 14/02/96
-GAME( 1997, monmouse,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Money Mouse (0400469V, NSW/ACT)",              MACHINE_FLAGS )  // 607/1, B - 08/04/97
-GAME( 2001, montree,   aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Money Tree (0201397V, New Zealand)",           MACHINE_FLAGS )  // MV4126, C - 12/04/01
-GAME( 1996, mountmon,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Mountain Money (0100294V, NSW/ACT)",           MACHINE_FLAGS )  //595/3, B - 11/06/96
-GAME( 2000, multidrw,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Multidraw - Free Games (0200956V, NSW/ACT)",   MACHINE_FLAGS )  // 386/64, E - 08/05/00
-GAME( 1996, mystgard,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Mystic Garden (0100275V, NSW/ACT)",            MACHINE_FLAGS )  // 595/1, B - 11/06/96
-GAME( 1999, orchidms,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Orchid Mist (0200849V, NSW/ACT)",              MACHINE_FLAGS )  // 601/3, C - 03/02/99
-GAME( 1996, oscara5,   aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Oscar (0200348V, NSW/ACT)",                    MACHINE_FLAGS )  // 593/2, C - 20/09/96
-GAME( 1999, pantmag,   aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Panther Magic (0101046V, NSW/ACT)",            MACHINE_FLAGS )  // 594/7, A - 06/10/99
-GAME( 2001, partygrs,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Party Gras (AHG1567, US)",                     MACHINE_FLAGS )  // MV4115/6, A - 10/11/01
-GAME( 2001, partygrsa, partygrs, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Party Gras (BHG1284, US)",                     MACHINE_FLAGS )  // MV4115/3, B - 06/02/01 - BAD DUMP
-GAME( 2000, peaflut,   aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Peacock Flutter (02J00011, NSW/ACT)",          MACHINE_FLAGS )  // JB001, A - 10/03/00
-GAME( 1997, pengpay,   aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Penguin Pays (0200460V, NSW/ACT)",             MACHINE_FLAGS )  // 586/4(a), D - 03/06/97
-GAME( 1996, pengpaya,  pengpay,  aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Penguin Pays (0200357V, NSW/ACT)",             MACHINE_FLAGS )  // 586/4, C - 12/11/96
-GAME( 1997, pengpayb,  pengpay,  aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Penguin Pays (0200359V, NSW/ACT)",             MACHINE_FLAGS )  // 586/3(a), D - 03/06/97
-GAME( 1997, pengpayu,  pengpay,  aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Penguin Pays (BHI0417-03, US)",                MACHINE_FLAGS )  // 586/7(b)  B - 14/07/97
-GAME( 1998, petshop,   aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Pet Shop (0100679V, NSW/ACT)",                 MACHINE_FLAGS )  // 618, A - 09/03/98 - BAD DUMP
-GAME( 1996, przfight,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Prize Fight (0100299V, NSW/ACT)",              MACHINE_FLAGS )  // 578/4, B - 08/08/96
-GAME( 1998, qcash,     aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Queens of Cash (0100706V, NSW/ACT)",           MACHINE_FLAGS )  // 603/6, C  - 23/07/98
-GAME( 1997, qnile,     aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Queen of the Nile (0100439V, NSW/ACT)",        MACHINE_FLAGS )  // 602/4, B - 13/05/97
-GAME( 1997, qnilea,    qnile,    aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Queen of the Nile (0300440V, NSW/ACT)",        MACHINE_FLAGS )  // 602/3, B - 13/05/97
-GAME( 1997, qnileb,    qnile,    aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Queen of the Nile (0200439V, NSW/ACT)",        MACHINE_FLAGS )  // 602/4,    B - 13/05/97
-GAME( 1997, qnilec,    qnile,    aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Queen of the Nile (0300439V, NSW/ACT)",        MACHINE_FLAGS )  // 602/4,    B - 13/05/97
-GAME( 1997, qnileu,    qnile,    aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Queen of the Nile (GHG4091-02, US)",           MACHINE_FLAGS )  // MV4091,   B - 13/05/97
-GAME( 1999, qnilemax,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Queen of the Nile - Maximillions (0401072V, NSW/ACT)", MACHINE_FLAGS )  // 602/4, D - 18/06/99
-GAME( 2000, rainwrce,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Rainbow Warriors - Cash Express (0101332V, NSW/ACT)",  MACHINE_FLAGS )  // 655, B - 02/03/00
-GAME( 1998, reelrock,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Reelin-n-Rockin (0100779V, NSW/ACT)",          MACHINE_FLAGS )  // 628,      A - 13/07/98
-GAME( 1997, retrsam,   aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Return of the Samurai (0400549V, NSW/ACT)",    MACHINE_FLAGS )  // 608, A - 17/04/97
-GAME( 1997, retrsama,  retrsam,  aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Return of the Samurai (0200506V, NSW/ACT)",    MACHINE_FLAGS )  // 608, A - 17/04/97
-GAME( 1997, retrsamb,  retrsam,  aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Return of the Samurai (0200549V, NSW/ACT)",    MACHINE_FLAGS )  // 608, A - 17/04/97
-GAME( 1997, sumospin,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Sumo Spins (0200606V, NSW/ACT)",               MACHINE_FLAGS )  // 622, A - 08/12/97
-GAME( 1999, sbuk2,     aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Super Bucks II (0400501V, NSW/ACT)",           MACHINE_FLAGS )  // 578, G - 26/07/99
-GAME( 1998, sbuk3,     aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Super Bucks III (0200711V, NSW/ACT)",          MACHINE_FLAGS )  // 626, A - 22/04/98
-GAME( 1995, swhr2,     aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Sweethearts II (0200004V, NSW/ACT)",           MACHINE_FLAGS )  // 577/1, C - 07/09/95
-GAME( 1998, swhr2u,    swhr2,    aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Sweethearts II (PHG0742-02, US)",              MACHINE_FLAGS )  // MV4061,   A - 29/06/98 - BAD DUMP
-GAME( 1995, swhr2v,    swhr2,    aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Sweet Hearts II (01J01986, Venezuela)",        MACHINE_FLAGS )  // 577/1,    C - 07/09/95
-GAME( 199?, topbana,   aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Top Banana (0100550V, NSW/ACT)",               MACHINE_FLAGS )  // BAD DUMP
-GAME( 2000, trstrove,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Treasure Trove (01J00161, NSW/ACT)",           MACHINE_FLAGS )  // JB001/3, A - 5/10/00
-GAME( 2002, tritreat,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Triple Treat (0201692V, NSW/ACT)",             MACHINE_FLAGS )  // 692, A - 17/05/02
-GAME( 2001, trojhors,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Trojan Horse (01J00851, NSW/ACT)",             MACHINE_FLAGS )  // JB001/5, A - 30/10/01
-GAME( 1997, trpdlght,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Tropical Delight (PHG0625-02, US)",            MACHINE_FLAGS )  // 577/3,    D - 24/09/97 - BAD DUMP
-GAME( 1998, unicornd,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Unicorn Dreaming (0100791V, NSW/ACT)",         MACHINE_FLAGS )  // 631/1, A - 31/08/98
-GAME( 2000, unicorndnz,unicornd, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Unicorn Dreaming (0101228V, New Zealand)",      MACHINE_FLAGS )  // MV4113/1, A - 05/04/2000
-GAME( 1996, wamazon,   aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Wild Amazon (0200285V, NSW/ACT)",              MACHINE_FLAGS )  // 506/6, A - 7/5/96
-GAME( 1996, wamazona,  wamazon,  aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Wild Amazon (0200507V, NSW/ACT)",              MACHINE_FLAGS )  // 506/8, A - 10/10/96
-GAME( 1996, wamazonv,  wamazon,  aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Wild Amazon (01J01996, Venezuela)",            MACHINE_FLAGS )  // 506/8, A - 10/10/96
-GAME( 1996, wildbill,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Wild Bill (0100297V, NSW/ACT)",                MACHINE_FLAGS )  // 543/8, C - 15/08/96
-GAME( 1996, wcougar,   aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Wild Cougar (0100167V, NSW/ACT)",              MACHINE_FLAGS )  // 569/9, B - 27/2/96
-GAME( 1997, wcougaru,  wcougar,  aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Wild Cougar (NHG0296-04, US)",                 MACHINE_FLAGS )  // 569/8,    D - 19/05/97
-GAME( 1999, wthing,    aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Wild Thing (0101158V, NSW/ACT)",               MACHINE_FLAGS )  // 608/4, B - 14/12/99
-GAME( 1999, wtiger,    aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "White Tiger Classic (0200954V, NSW/ACT)",      MACHINE_FLAGS )  // 638/1,    B - 08/07/99
+GAMEL( 1998, adonis,    aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Adonis (0200751V, NSW/ACT)",                   MACHINE_FLAGS, layout_aristmk5 )  // 602/9,    A - 25/05/98, Rev 10
+GAMEL( 1998, adonisa,   adonis,   aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Adonis (0100751V, NSW/ACT)",                   MACHINE_FLAGS, layout_aristmk5 )  // 602/9,    A - 25/05/98, Rev 9
+GAMEL( 2001, adonisu,   adonis,   aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Adonis (BHG1508, US)",                         MACHINE_FLAGS, layout_aristmk5 )  // MV4124/1, B - 31/07/01 - BAD DUMP
+GAMEL( 1999, adonisce,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Adonis - Cash Express (0201005V, NSW/ACT)",    MACHINE_FLAGS, layout_aristmk5 )  // 602/9, C - 06/07/99
+GAMEL( 1996, baddog,    aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Bad Dog Poker (0200428V, NSW/ACT)",            MACHINE_FLAGS, layout_aristmk5 )  // 386/56, A - 17/12/96
+GAMEL( 1996, blackpnt,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Black Panther (0200818V, Victoria)",           MACHINE_FLAGS, layout_aristmk5 )  // 594/1, A - 30/07/96
+GAMEL( 1998, bootsctn,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Boot Scootin' (0100812V, NSW/ACT)",            MACHINE_FLAGS, layout_aristmk5 )  // 616/1, B - 11/12/98
+GAMEL( 1999, bootsctnu, bootsctn, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Boot Scootin' (GHG1012-02, US)",               MACHINE_FLAGS, layout_aristmk5 )  // MV4098,   A - 25/08/99 - BAD DUMP
+GAMEL( 1996, bumblbug,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Bumble Bugs (0200510V, NSW/ACT)",              MACHINE_FLAGS, layout_aristmk5 )  // 593, D - 5/07/96
+GAMEL( 1996, bumblbugql,bumblbug, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Bumble Bugs (0200456V, Queensland)",           MACHINE_FLAGS, layout_aristmk5 )  // 593,      D - 5/07/96
+GAMEL( 1997, bumblbugu, bumblbug, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Bumble Bugs (CHG0479-03, US)",                 MACHINE_FLAGS, layout_aristmk5 )  // 593,      D - 05/07/97 - BAD DUMP
+GAMEL( 1995, buttdeli,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Butterfly Delight (0200143V, NSW/ACT)",        MACHINE_FLAGS, layout_aristmk5 )  // 571/4, A - 19/12/95
+GAMEL( 1999, cashcat,   aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Cash Cat (0300863V, New Zealand)",             MACHINE_FLAGS, layout_aristmk5 )  // MV4089, A - 4/1/99
+GAMEL( 1997, cashcham,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Cash Chameleon (0100438V, NSW/ACT)",           MACHINE_FLAGS, layout_aristmk5 )  // 603/1, C  - 15/4/97
+GAMEL( 1996, cashchamu, cashcham, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Cash Chameleon (DHG4078-99, US)",              MACHINE_FLAGS, layout_aristmk5 )  // 603(a),   B - 06/12/96 - BAD DUMP
+GAMEL( 1998, cashchama, cashcham, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Cash Chameleon (0200437V, NSW/ACT)",           MACHINE_FLAGS, layout_aristmk5 )  // 603(a), D - 18/02/98
+GAMEL( 1998, cashchamnz,cashcham, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Cash Chameleon (0300781V, New Zealand)",       MACHINE_FLAGS, layout_aristmk5 )  // MV4067, A - 31/08/98
+GAMEL( 1997, cashcra5,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Cash Crop (0300467V, NSW/ACT)",                MACHINE_FLAGS, layout_aristmk5 )  // 607, C - 14/07/97
+GAMEL( 1998, chariotc,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "The Chariot Challenge (04J00714, NSW/ACT)",    MACHINE_FLAGS, layout_aristmk5 )  // 630,      A - 10/08/98, Rev 12
+GAMEL( 1998, chariotca, chariotc, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "The Chariot Challenge (0100787V, NSW/ACT)",    MACHINE_FLAGS, layout_aristmk5 )  // 630/1, A - 10/08/98
+GAMEL( 2001, checkma5,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Checkmate (01J00681, NSW/ACT)",                MACHINE_FLAGS, layout_aristmk5 )  // JB011, B - 06/07/01
+GAMEL( 1996, chickna5,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Chicken (0100351V, NSW/ACT)",                  MACHINE_FLAGS, layout_aristmk5 )  // 596, A - 27/08/96
+GAMEL( 1998, chickna5u, chickna5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Chicken (RHG0730-03, US)",                     MACHINE_FLAGS, layout_aristmk5 )  // 596,      C - 23/02/98 - BAD DUMP
+GAMEL( 1998, chickna5qld,chickna5,aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Chicken (0200530V, Queensland)",               MACHINE_FLAGS, layout_aristmk5 )  // 596, C - 23/02/98
+GAMEL( 1998, coralrc2,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Coral Riches II (0100919V, NSW/ACT)",          MACHINE_FLAGS, layout_aristmk5 )  // 577/7, A - 29/12/98
+GAMEL( 1998, cuckoo,    aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Cuckoo (0200753V, NSW/ACT)",                   MACHINE_FLAGS, layout_aristmk5 )  // 615/1, D - 03/07/98
+GAMEL( 2000, cuckoou,   cuckoo,   aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Cuckoo (CHG1195, US)",                         MACHINE_FLAGS, layout_aristmk5 )  // MV4104,   C - 02/02/00
+GAMEL( 1995, dstbloom,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Desert Bloom (0200111V, NSW/ACT)",             MACHINE_FLAGS, layout_aristmk5 )  // 577/2, A - 12/10/95
+GAMEL( 1999, diamdove,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Diamond Dove (0101018V, NSW/ACT)",             MACHINE_FLAGS, layout_aristmk5 )  // 640, B - 19/05/99
+GAMEL( 1996, dmdfever,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Diamond Fever (0200302V, NSW/ACT)",            MACHINE_FLAGS, layout_aristmk5 )  // 483/7, E - 05/09/96
+GAMEL( 1997, dimtouch,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Diamond Touch (0400433V, NSW/ACT)",            MACHINE_FLAGS, layout_aristmk5 )  // 604,      E - 30/06/97
+GAMEL( 1996, dolphntr,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Dolphin Treasure (0200424V, NSW/ACT)",         MACHINE_FLAGS, layout_aristmk5 )  // 602/1,    B - 06/12/96, Rev 3
+GAMEL( 1996, dolphntra, dolphntr, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Dolphin Treasure (0100424V, NSW/ACT)",         MACHINE_FLAGS, layout_aristmk5 )  // 602/1,    B - 06/12/96, Rev 1.24.4.0
+GAMEL( 1996, dolphntrb, dolphntr, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Dolphin Treasure (0100388V, NSW/ACT)",         MACHINE_FLAGS, layout_aristmk5 )  // 602, B - 10/12/96
+GAMEL( 1996, dolphntru, dolphntr, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Dolphin Treasure (FHG4077-02, US)",            MACHINE_FLAGS, layout_aristmk5 )  // 602/1,    B - 06/12/96
+GAMEL( 2000, dynajack,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Dynamite Jack (01J00081, NSW/ACT)",            MACHINE_FLAGS, layout_aristmk5 )  // JB004, A - 12/07/2000
+GAMEL( 1998, eldorda5,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "El Dorado (0100652V, NSW/ACT)",                MACHINE_FLAGS, layout_aristmk5 )  // 623, B - 24/03/98
+GAMEL( 1995, eforsta5,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Enchanted Forest (0400122V, NSW/ACT)",         MACHINE_FLAGS, layout_aristmk5 )  // 570/3,    E - 23/06/95
+GAMEL( 1997, eforsta5u, eforsta5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Enchanted Forest (JHG0415-03, US)",            MACHINE_FLAGS, layout_aristmk5 )  // MV4033,   B - 10/02/97
+GAMEL( 2000, fortellr,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Fortune Teller (01J00131, NSW/ACT)",           MACHINE_FLAGS, layout_aristmk5 )  // JB006, D - 24/11/2000
+GAMEL( 1998, gambler,   aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "The Gambler (EHG0916-02, US)",                 MACHINE_FLAGS, layout_aristmk5 )  // MV4084/1, A - 30/10/98 - POSSIBLE BAD DUMP
+GAMEL( 2001, geisha,    aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Geisha (0101408V, New Zealand)",               MACHINE_FLAGS, layout_aristmk5 )  // MV4127,   A - 05/03/01
+GAMEL( 1999, genmagi,   aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Genie Magic (0200894V, NSW/ACT)",              MACHINE_FLAGS, layout_aristmk5 )  // ???,   C - 15/02/99
+GAMEL( 1998, gnomeatw,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Gnome Around The World (0100767V, NSW/ACT)",   MACHINE_FLAGS, layout_aristmk5 )  // 625, C - 18/12/98
+GAMEL( 1997, goldpyr,   aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Golden Pyramids (AHG1205-03, US)",             MACHINE_FLAGS, layout_aristmk5 )  // MV4091,   B - 13/05/97
+GAMEL( 1997, goldpyra,  goldpyr,  aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Golden Pyramids (AHG1206-99, US)",             MACHINE_FLAGS, layout_aristmk5 )  // 602/2,    B - 13/05/97 - BAD DUMP
+GAMEL( 2000, goldenra,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Golden Ra (0101164V, NSW/ACT)",                MACHINE_FLAGS, layout_aristmk5 )  // 661, A - 10/04/00
+GAMEL( 1999, incasun,   aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Inca Sun (0100872V, NSW/ACT)",                 MACHINE_FLAGS, layout_aristmk5 )  // 631/3 B, B - 03/05/99
+GAMEL( 1999, incasunsp, incasun,  aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Inca Sun (0100872V, NSW/ACT, Show Program)",   MACHINE_FLAGS, layout_aristmk5 )  // 631/3 B, B - 03/05/99
+GAMEL( 2000, incasunnz, incasun,  aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Inca Sun (0101108V, New Zealand)",             MACHINE_FLAGS, layout_aristmk5 )  // MV4113, A - 6/3/00
+GAMEL( 2000, incasunu,  incasun,  aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Inca Sun (CHG1458, US)",                       MACHINE_FLAGS, layout_aristmk5 )  // MV4130/3, A - 05/09/00
+GAMEL( 1998, indrema5,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Indian Dreaming (0100845V, NSW/ACT)",          MACHINE_FLAGS, layout_aristmk5 )  // 628/1,    B - 15/12/98
+GAMEL( 1996, jungjuic,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Jungle Juice (0200240V, New Zealand)",         MACHINE_FLAGS, layout_aristmk5 )  // 566/3, F - 06/03/96
+GAMEL( 1995, kgalah,    aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "King Galah (0200536V, NSW/ACT)",               MACHINE_FLAGS, layout_aristmk5 )  // 613/6, A - 21/07/95
+GAMEL( 2001, koalamnt,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Koala Mint (CHG1573, US)",                     MACHINE_FLAGS, layout_aristmk5 )  // MV4137,   A - 12/09/01 - BAD DUMP
+GAMEL( 1998, kookabuk,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Kooka Bucks (0100677V, NSW/ACT)",              MACHINE_FLAGS, layout_aristmk5 )  // 661, A - 03/04/98
+GAMEL( 1997, locoloot,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Loco Loot (0100472V, NSW/ACT)",                MACHINE_FLAGS, layout_aristmk5 )  // 599/2, C - 17/06/97
+GAMEL( 1998, locolootnz,locoloot, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Loco Loot (0600725V, New Zealand)",            MACHINE_FLAGS, layout_aristmk5 )  // MV4064, A - 8/7/98
+GAMEL( 1997, lonewolf,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Lone Wolf (0100587V, NSW/ACT)",                MACHINE_FLAGS, layout_aristmk5 )  // 621, A - 29/10/97
+GAMEL( 1997, mgarden,   aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Magic Garden (AHG1211-99, US)",                MACHINE_FLAGS, layout_aristmk5 )  // MV4033,   B - 10/02/97 - BAD DUMP
+GAMEL( 2000, magimask,  aristmk5, aristmk5_usa_touch, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Magic Mask (DHG1309, US)",                     MACHINE_FLAGS, layout_aristmk5 )  // MV4115,   A - 09/05/00
+GAMEL( 2000, magimaska, magimask, aristmk5_usa_touch, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Magic Mask (AHG1548, US)",                     MACHINE_FLAGS, layout_aristmk5 )  // MV4115,   A - 09/05/00
+GAMEL( 1997, magtcha5,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Magic Touch (0200455V, NSW/ACT)",              MACHINE_FLAGS, layout_aristmk5 )  // 606, A - 06/03/97
+GAMEL( 2000, marmagic,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Margarita Magic (01J00101, NSW/ACT)",          MACHINE_FLAGS, layout_aristmk5 )  // JB005,    A - 07/07/00
+GAMEL( 2000, marmagicu, marmagic, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Margarita Magic (EHG1559, US)",                MACHINE_FLAGS, layout_aristmk5 )  // US003,    A - 07/07/00 - BAD DUMP
+GAMEL( 1996, minemine,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Mine, Mine, Mine (VHG0416-99, US)",            MACHINE_FLAGS, layout_aristmk5 )  // 559/2,    E - 14/02/96
+GAMEL( 1997, monmouse,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Money Mouse (0400469V, NSW/ACT)",              MACHINE_FLAGS, layout_aristmk5 )  // 607/1, B - 08/04/97
+GAMEL( 2001, montree,   aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Money Tree (0201397V, New Zealand)",           MACHINE_FLAGS, layout_aristmk5 )  // MV4126, C - 12/04/01
+GAMEL( 1996, mountmon,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Mountain Money (0100294V, NSW/ACT)",           MACHINE_FLAGS, layout_aristmk5 )  //595/3, B - 11/06/96
+GAMEL( 2000, multidrw,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Multidraw - Free Games (0200956V, NSW/ACT)",   MACHINE_FLAGS, layout_aristmk5 )  // 386/64, E - 08/05/00
+GAMEL( 1996, mystgard,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Mystic Garden (0100275V, NSW/ACT)",            MACHINE_FLAGS, layout_aristmk5 )  // 595/1, B - 11/06/96
+GAMEL( 1999, orchidms,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Orchid Mist (0200849V, NSW/ACT)",              MACHINE_FLAGS, layout_aristmk5 )  // 601/3, C - 03/02/99
+GAMEL( 1996, oscara5,   aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Oscar (0200348V, NSW/ACT)",                    MACHINE_FLAGS, layout_aristmk5 )  // 593/2, C - 20/09/96
+GAMEL( 1999, pantmag,   aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Panther Magic (0101046V, NSW/ACT)",            MACHINE_FLAGS, layout_aristmk5 )  // 594/7, A - 06/10/99
+GAMEL( 2001, partygrs,  aristmk5, aristmk5_usa_touch, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Party Gras (AHG1567, US)",                     MACHINE_FLAGS, layout_aristmk5 )  // MV4115/6, A - 10/11/01
+GAMEL( 2001, partygrsa, partygrs, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Party Gras (BHG1284, US)",                     MACHINE_FLAGS, layout_aristmk5 )  // MV4115/3, B - 06/02/01 - BAD DUMP
+GAMEL( 2000, peaflut,   aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Peacock Flutter (02J00011, NSW/ACT)",          MACHINE_FLAGS, layout_aristmk5 )  // JB001, A - 10/03/00
+GAMEL( 1997, pengpay,   aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Penguin Pays (0200460V, NSW/ACT)",             MACHINE_FLAGS, layout_aristmk5 )  // 586/4(a), D - 03/06/97
+GAMEL( 1996, pengpaya,  pengpay,  aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Penguin Pays (0200357V, NSW/ACT)",             MACHINE_FLAGS, layout_aristmk5 )  // 586/4, C - 12/11/96
+GAMEL( 1997, pengpayb,  pengpay,  aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Penguin Pays (0200359V, NSW/ACT)",             MACHINE_FLAGS, layout_aristmk5 )  // 586/3(a), D - 03/06/97
+GAMEL( 1997, pengpayu,  pengpay,  aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Penguin Pays (BHI0417-03, US)",                MACHINE_FLAGS, layout_aristmk5 )  // 586/7(b)  B - 14/07/97
+GAMEL( 1998, petshop,   aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Pet Shop (0100679V, NSW/ACT)",                 MACHINE_FLAGS, layout_aristmk5 )  // 618, A - 09/03/98 - BAD DUMP
+GAMEL( 1996, przfight,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Prize Fight (0100299V, NSW/ACT)",              MACHINE_FLAGS, layout_aristmk5 )  // 578/4, B - 08/08/96
+GAMEL( 1998, qcash,     aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Queens of Cash (0100706V, NSW/ACT)",           MACHINE_FLAGS, layout_aristmk5 )  // 603/6, C  - 23/07/98
+GAMEL( 1997, qnile,     aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Queen of the Nile (0100439V, NSW/ACT)",        MACHINE_FLAGS, layout_aristmk5 )  // 602/4, B - 13/05/97
+GAMEL( 1997, qnilea,    qnile,    aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Queen of the Nile (0300440V, NSW/ACT)",        MACHINE_FLAGS, layout_aristmk5 )  // 602/3, B - 13/05/97
+GAMEL( 1997, qnileb,    qnile,    aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Queen of the Nile (0200439V, NSW/ACT)",        MACHINE_FLAGS, layout_aristmk5 )  // 602/4,    B - 13/05/97
+GAMEL( 1997, qnilec,    qnile,    aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Queen of the Nile (0300439V, NSW/ACT)",        MACHINE_FLAGS, layout_aristmk5 )  // 602/4,    B - 13/05/97
+GAMEL( 1997, qnileu,    qnile,    aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Queen of the Nile (GHG4091-02, US)",           MACHINE_FLAGS, layout_aristmk5 )  // MV4091,   B - 13/05/97
+GAMEL( 1999, qnilemax,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Queen of the Nile - Maximillions (0401072V, NSW/ACT)", MACHINE_FLAGS, layout_aristmk5 )  // 602/4, D - 18/06/99
+GAMEL( 2000, rainwrce,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Rainbow Warriors - Cash Express (0101332V, NSW/ACT)",  MACHINE_FLAGS, layout_aristmk5 )  // 655, B - 02/03/00
+GAMEL( 1998, reelrock,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Reelin-n-Rockin (0100779V, NSW/ACT)",          MACHINE_FLAGS, layout_aristmk5 )  // 628,      A - 13/07/98
+GAMEL( 1997, retrsam,   aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Return of the Samurai (0400549V, NSW/ACT)",    MACHINE_FLAGS, layout_aristmk5 )  // 608, A - 17/04/97
+GAMEL( 1997, retrsama,  retrsam,  aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Return of the Samurai (0200506V, NSW/ACT)",    MACHINE_FLAGS, layout_aristmk5 )  // 608, A - 17/04/97
+GAMEL( 1997, retrsamb,  retrsam,  aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Return of the Samurai (0200549V, NSW/ACT)",    MACHINE_FLAGS, layout_aristmk5 )  // 608, A - 17/04/97
+GAMEL( 1997, sumospin,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Sumo Spins (0200606V, NSW/ACT)",               MACHINE_FLAGS, layout_aristmk5 )  // 622, A - 08/12/97
+GAMEL( 1999, sbuk2,     aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Super Bucks II (0400501V, NSW/ACT)",           MACHINE_FLAGS, layout_aristmk5 )  // 578, G - 26/07/99
+GAMEL( 1998, sbuk3,     aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Super Bucks III (0200711V, NSW/ACT)",          MACHINE_FLAGS, layout_aristmk5 )  // 626, A - 22/04/98
+GAMEL( 1995, swhr2,     aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Sweethearts II (0200004V, NSW/ACT)",           MACHINE_FLAGS, layout_aristmk5 )  // 577/1, C - 07/09/95
+GAMEL( 1998, swhr2u,    swhr2,    aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Sweethearts II (PHG0742-02, US)",              MACHINE_FLAGS, layout_aristmk5 )  // MV4061,   A - 29/06/98 - BAD DUMP
+GAMEL( 1995, swhr2v,    swhr2,    aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Sweet Hearts II (01J01986, Venezuela)",        MACHINE_FLAGS, layout_aristmk5 )  // 577/1,    C - 07/09/95
+GAMEL( 199?, topbana,   aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Top Banana (0100550V, NSW/ACT)",               MACHINE_FLAGS, layout_aristmk5 )  // BAD DUMP
+GAMEL( 2000, trstrove,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Treasure Trove (01J00161, NSW/ACT)",           MACHINE_FLAGS, layout_aristmk5 )  // JB001/3, A - 5/10/00
+GAMEL( 2002, tritreat,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Triple Treat (0201692V, NSW/ACT)",             MACHINE_FLAGS, layout_aristmk5 )  // 692, A - 17/05/02
+GAMEL( 2001, trojhors,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Trojan Horse (01J00851, NSW/ACT)",             MACHINE_FLAGS, layout_aristmk5 )  // JB001/5, A - 30/10/01
+GAMEL( 1997, trpdlght,  aristmk5, aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Tropical Delight (PHG0625-02, US)",            MACHINE_FLAGS, layout_aristmk5 )  // 577/3,    D - 24/09/97 - BAD DUMP
+GAMEL( 1998, unicornd,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Unicorn Dreaming (0100791V, NSW/ACT)",         MACHINE_FLAGS, layout_aristmk5 )  // 631/1, A - 31/08/98
+GAMEL( 2000, unicorndnz,unicornd, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Unicorn Dreaming (0101228V, New Zealand)",     MACHINE_FLAGS, layout_aristmk5 )  // MV4113/1, A - 05/04/2000
+GAMEL( 1996, wamazon,   aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Wild Amazon (0200285V, NSW/ACT)",              MACHINE_FLAGS, layout_aristmk5 )  // 506/6, A - 7/5/96
+GAMEL( 1996, wamazona,  wamazon,  aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Wild Amazon (0200507V, NSW/ACT)",              MACHINE_FLAGS, layout_aristmk5 )  // 506/8, A - 10/10/96
+GAMEL( 1996, wamazonv,  wamazon,  aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Wild Amazon (01J01996, Venezuela)",            MACHINE_FLAGS, layout_aristmk5 )  // 506/8, A - 10/10/96
+GAMEL( 1996, wildbill,  aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Wild Bill (0100297V, NSW/ACT)",                MACHINE_FLAGS, layout_aristmk5 )  // 543/8, C - 15/08/96
+GAMEL( 1996, wcougar,   aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Wild Cougar (0100167V, NSW/ACT)",              MACHINE_FLAGS, layout_aristmk5 )  // 569/9, B - 27/2/96
+GAMEL( 1997, wcougaru,  wcougar,  aristmk5_usa, aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Wild Cougar (NHG0296-04, US)",                 MACHINE_FLAGS, layout_aristmk5 )  // 569/8,    D - 19/05/97
+GAMEL( 1999, wthing,    aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "Wild Thing (0101158V, NSW/ACT)",               MACHINE_FLAGS, layout_aristmk5 )  // 608/4, B - 14/12/99
+GAMEL( 1999, wtiger,    aristmk5, aristmk5,     aristmk5, aristmk5_state, aristmk5, ROT0, "Aristocrat", "White Tiger Classic (0200954V, NSW/ACT)",      MACHINE_FLAGS, layout_aristmk5 )  // 638/1,    B - 08/07/99
 
diff --git a/src/mame/drivers/aristmk6.cpp b/src/mame/drivers/aristmk6.cpp
index 1ba3987..bbe8262 100644
--- a/src/mame/drivers/aristmk6.cpp
+++ b/src/mame/drivers/aristmk6.cpp
@@ -650,7 +650,7 @@ ROM_START( apocof )
 	ROM_LOAD32_WORD("0151105.u86", 0x0000000, 0x0400000, CRC(d1f0a2a6) SHA1(d88fd4153b9a5f655c7949883caf3f947a50652f) )
 	ROM_LOAD32_WORD("0151105.u73", 0x0000002, 0x0400000, CRC(675ee721) SHA1(3f4afe6196fc39c2544fc3731f39adef0198b9a3) )
 	ROM_LOAD32_WORD("0151105.u85", 0x0800000, 0x0400000, CRC(daa8cc4f) SHA1(2a71c7dbd0691654b614fcd09dae4ff47a60b655) )
-	ROM_LOAD32_WORD("0151105.u72", 0x0800002, 0x01c0000, CRC(f3733388) SHA1(cf01799770b785a0f7527aedf627f16642a60ff3) )
+	ROM_LOAD32_WORD("0151105.u72", 0x0800002, 0x01c0000, BAD_DUMP CRC(f3733388) SHA1(cf01799770b785a0f7527aedf627f16642a60ff3) )
 ROM_END
 
 
diff --git a/src/mame/drivers/armedf.cpp b/src/mame/drivers/armedf.cpp
index 3eb8fa8..3c72af7 100644
--- a/src/mame/drivers/armedf.cpp
+++ b/src/mame/drivers/armedf.cpp
@@ -527,6 +527,7 @@ READ16_MEMBER(bigfghtr_state::latch_r)
 
 WRITE16_MEMBER(bigfghtr_state::sharedram_w)
 {
+	data &= mem_mask;
 	COMBINE_DATA(&m_sharedram[offset]);
 
 	switch(offset)
diff --git a/src/mame/drivers/astinvad.cpp b/src/mame/drivers/astinvad.cpp
index 5fcc283..9eb6740 100644
--- a/src/mame/drivers/astinvad.cpp
+++ b/src/mame/drivers/astinvad.cpp
@@ -39,7 +39,8 @@ enum
 	SND_FLEET2,
 	SND_FLEET3,
 	SND_FLEET4,
-	SND_UFOHIT
+	SND_UFOHIT,
+	SND_BONUS
 };
 
 
@@ -53,31 +54,15 @@ public:
 	};
 
 	astinvad_state(const machine_config &mconfig, device_type type, const char *tag)
-		: driver_device(mconfig, type, tag),
-		m_maincpu(*this, "maincpu"),
-		m_ppi8255_0(*this, "ppi8255_0"),
-		m_ppi8255_1(*this, "ppi8255_1"),
-		m_palette(*this, "palette"),
-		m_videoram(*this, "videoram"),
-		m_samples(*this, "samples"),
-		m_screen(*this, "screen"){ }
-
-	required_device<cpu_device> m_maincpu;
-	optional_device<i8255_device>  m_ppi8255_0;
-	optional_device<i8255_device>  m_ppi8255_1;
-	required_device<palette_device> m_palette;
-	required_shared_ptr<uint8_t> m_videoram;
-
-	std::unique_ptr<uint8_t[]>    m_colorram;
-	emu_timer  *m_int_timer;
-	uint8_t      m_sound_state[2];
-	uint8_t      m_screen_flip;
-	uint8_t      m_screen_red;
-	uint8_t      m_flip_yoffs;
-	uint8_t      m_color_latch;
-
-	required_device<samples_device> m_samples;
-	required_device<screen_device> m_screen;
+		: driver_device(mconfig, type, tag)
+		, m_maincpu(*this, "maincpu")
+		, m_ppi8255_0(*this, "ppi8255_0")
+		, m_ppi8255_1(*this, "ppi8255_1")
+		, m_palette(*this, "palette")
+		, m_videoram(*this, "videoram")
+		, m_samples(*this, "samples")
+		, m_screen(*this, "screen")
+		{ }
 
 	DECLARE_WRITE8_MEMBER(color_latch_w);
 	DECLARE_WRITE8_MEMBER(spaceint_videoram_w);
@@ -99,13 +84,31 @@ public:
 	DECLARE_MACHINE_RESET(spaceint);
 	DECLARE_VIDEO_START(spaceint);
 	uint32_t screen_update_astinvad(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+	uint32_t screen_update_spcking2(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
 	uint32_t screen_update_spaceint(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
 	TIMER_CALLBACK_MEMBER(kamikaze_int_off);
 	TIMER_CALLBACK_MEMBER(kamizake_int_gen);
-	void plot_byte( bitmap_rgb32 &bitmap, uint8_t y, uint8_t x, uint8_t data, uint8_t color );
 
-protected:
+private:
 	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+	void plot_byte( bitmap_rgb32 &bitmap, uint8_t y, uint8_t x, uint8_t data, uint8_t color );
+
+	std::unique_ptr<uint8_t[]>    m_colorram;
+	emu_timer  *m_int_timer;
+	uint8_t      m_sound_state[2];
+	uint8_t      m_screen_flip;
+	uint8_t      m_screen_red;
+	uint8_t      m_flip_yoffs;
+	uint8_t      m_color_latch;
+	bool         m_player;
+
+	required_device<cpu_device> m_maincpu;
+	optional_device<i8255_device>  m_ppi8255_0;
+	optional_device<i8255_device>  m_ppi8255_1;
+	required_device<palette_device> m_palette;
+	required_shared_ptr<uint8_t> m_videoram;
+	required_device<samples_device> m_samples;
+	required_device<screen_device> m_screen;
 };
 
 
@@ -178,6 +181,25 @@ uint32_t astinvad_state::screen_update_astinvad(screen_device &screen, bitmap_rg
 }
 
 
+uint32_t astinvad_state::screen_update_spcking2(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+	const uint8_t *color_prom = memregion("proms")->base();
+	uint8_t yoffs = m_flip_yoffs & m_screen_flip;
+	int x, y;
+
+	/* render the visible pixels */
+	for (y = cliprect.min_y; y <= cliprect.max_y; y++)
+		for (x = cliprect.min_x & ~7; x <= cliprect.max_x; x += 8)
+		{
+			uint8_t color = color_prom[(((y & 0xf8) << 2) | (x >> 3)) ^ (m_screen_flip ? 0x3ff : m_player ? 0 : 0x3ff)] >> (m_player ? 4 : 0);
+			uint8_t data = m_videoram[(((y ^ m_screen_flip) + yoffs) << 5) | ((x ^ m_screen_flip) >> 3)];
+			plot_byte(bitmap, y, x, data, m_screen_red ? 1 : color & 0x07);
+		}
+
+	return 0;
+}
+
+
 uint32_t astinvad_state::screen_update_spaceint(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
 {
 	const uint8_t *color_prom = memregion("proms")->base();
@@ -349,7 +371,7 @@ WRITE8_MEMBER(astinvad_state::kamikaze_sound1_w)
 	if (bits_gone_hi & 0x02) m_samples->start(1, SND_SHOT);
 	if (bits_gone_hi & 0x04) m_samples->start(2, SND_BASEHIT);
 	if (bits_gone_hi & 0x08) m_samples->start(3, SND_INVADERHIT);
-	if (bits_gone_hi & 0x10) m_samples->start(3, SND_INVADERHIT);
+	if (bits_gone_hi & 0x10) m_samples->start(2, SND_BONUS);
 
 	machine().sound().system_enable(data & 0x20);
 }
@@ -383,7 +405,7 @@ WRITE8_MEMBER(astinvad_state::spcking2_sound1_w)
 	if (bits_gone_hi & 0x02) m_samples->start(1, SND_SHOT);
 	if (bits_gone_hi & 0x04) m_samples->start(2, SND_BASEHIT);
 	if (bits_gone_hi & 0x08) m_samples->start(3, SND_INVADERHIT);
-
+	if (bits_gone_hi & 0x10) m_samples->start(2, SND_BONUS);
 	machine().sound().system_enable(data & 0x20);
 	m_screen_red = data & 0x04; // ?
 }
@@ -400,6 +422,7 @@ WRITE8_MEMBER(astinvad_state::spcking2_sound2_w)
 	if (bits_gone_hi & 0x10) m_samples->start(4, SND_UFOHIT);
 
 	m_screen_flip = (ioport("CABINET")->read() & data & 0x20) ? 0xff : 0x00;
+	m_player = BIT(data, 5);
 }
 
 WRITE8_MEMBER(astinvad_state::spcking2_sound3_w)
@@ -618,6 +641,7 @@ static const char *const astinvad_sample_names[] =
 	"6",
 	"7",
 	"8",
+	"9",
 	nullptr
 };
 
@@ -675,6 +699,7 @@ static MACHINE_CONFIG_DERIVED( spcking2, kamikaze )
 	/* video hardware */
 	MCFG_SCREEN_MODIFY("screen")
 	MCFG_SCREEN_RAW_PARAMS(VIDEO_CLOCK, 320, 0, 256, 256, 16, 240)
+	MCFG_SCREEN_UPDATE_DRIVER(astinvad_state, screen_update_spcking2)
 MACHINE_CONFIG_END
 
 
diff --git a/src/mame/drivers/astrocde.cpp b/src/mame/drivers/astrocde.cpp
index 82d3145..864c8bd 100644
--- a/src/mame/drivers/astrocde.cpp
+++ b/src/mame/drivers/astrocde.cpp
@@ -120,9 +120,7 @@
 #include "machine/z80ctc.h"
 #include "machine/nvram.h"
 #include "sound/ay8910.h"
-
-#include "audio/wow.h"
-#include "audio/gorf.h"
+#include "sound/votrax.h"
 
 #include "gorf.lh"
 #include "seawolf2.lh"
@@ -292,7 +290,6 @@ READ8_MEMBER(astrocde_state::wow_io_r)
 }
 
 
-
 /*************************************
  *
  *  Gorf specific input/output
@@ -313,11 +310,7 @@ READ8_MEMBER(astrocde_state::gorf_io_1_r)
 		case 5: m_sparkle[3] = data;    break;
 		case 6:
 			m_astrocade_sound1->set_output_gain(0, data ? 0.0 : 1.0);
-#if USE_FAKE_VOTRAX
-			m_samples->set_output_gain(0, data ? 1.0 : 0.0);
-#else
 			m_votrax->set_output_gain(0, data ? 1.0 : 0.0);
-#endif
 			break;
 		case 7: osd_printf_debug("io_1:%d\n", data); break;
 	}
@@ -512,6 +505,28 @@ WRITE8_MEMBER(astrocde_state::tenpindx_lights_w)
 }
 
 
+/*************************************
+ *
+ *  Votrax SC01 specific input/output
+ *
+ *************************************/
+
+READ8_MEMBER( astrocde_state::votrax_speech_r )
+{
+	uint8_t data = offset >> 8;
+	m_votrax->inflection_w(space, 0, data >> 6);
+	m_votrax->write(space, 0, data);
+
+	/* Note : We should really also use volume in this as well as frequency */
+	return data;                                   /* Return nicely */
+}
+
+
+CUSTOM_INPUT_MEMBER( astrocde_state::votrax_speech_status_r )
+{
+	return m_votrax->request();
+}
+
 
 /*************************************
  *
@@ -879,7 +894,7 @@ static INPUT_PORTS_START( wow )
 	PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON2 )
 	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 )
 	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
-	PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, astrocde_state, wow_speech_status_r, nullptr)
+	PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, astrocde_state, votrax_speech_status_r, nullptr)
 
 	PORT_START("P4HANDLE")
 	/* "If S1:1,2,3 are all ON or all OFF, only coin meter number 1 will count." */
@@ -949,7 +964,7 @@ static INPUT_PORTS_START( gorf )
 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY
 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 )
 	PORT_BIT( 0x60, IP_ACTIVE_LOW, IPT_UNUSED )
-	PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, astrocde_state, gorf_speech_status_r, nullptr)
+	PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, astrocde_state, votrax_speech_status_r, nullptr)
 
 	PORT_START("P4HANDLE")
 	PORT_DIPNAME( 0x01, 0x01, DEF_STR( Coin_A ) )       PORT_DIPLOCATION("S1:1")
@@ -1354,13 +1369,7 @@ static MACHINE_CONFIG_DERIVED( wow, astrocade_base )
 	/* sound hardware */
 	MCFG_SPEAKER_ADD("center", 0.0, 0.0, 1.0)
 
-#if USE_FAKE_VOTRAX
-	MCFG_SOUND_ADD("samples", SAMPLES, 0)
-	MCFG_SAMPLES_CHANNELS(1)
-	MCFG_SAMPLES_NAMES(wow_sample_names)
-#else
-	MCFG_VOTRAX_SC01_ADD("votrax", VOTRAX_SC01, 720000)
-#endif
+	MCFG_SOUND_ADD("votrax", VOTRAX_SC01, 720000)
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "center", 0.85)
 MACHINE_CONFIG_END
 
@@ -1386,13 +1395,7 @@ static MACHINE_CONFIG_DERIVED( gorf, astrocade_base )
 	MCFG_ASTROCADE_ADD("astrocade2", ASTROCADE_CLOCK/4)
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lower", 1.0)
 
-#if USE_FAKE_VOTRAX
-	MCFG_SOUND_ADD("samples", SAMPLES, 0)
-	MCFG_SAMPLES_CHANNELS(1)
-	MCFG_SAMPLES_NAMES(gorf_sample_names)
-#else
-	MCFG_VOTRAX_SC01_ADD("votrax", VOTRAX_SC01, 720000)
-#endif
+	MCFG_SOUND_ADD("votrax", VOTRAX_SC01, 720000)
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "upper", 0.85)
 MACHINE_CONFIG_END
 
@@ -1709,7 +1712,7 @@ DRIVER_INIT_MEMBER(astrocde_state,wow)
 {
 	m_video_config = AC_SOUND_PRESENT | AC_LIGHTPEN_INTS | AC_STARS;
 	m_maincpu->space(AS_IO).install_read_handler(0x15, 0x15, 0, 0xf000, 0x0f00, read8_delegate(FUNC(astrocde_state::wow_io_r), this));
-	m_maincpu->space(AS_IO).install_read_handler(0x17, 0x17, 0, 0x0000, 0xff00, read8_delegate(FUNC(astrocde_state::wow_speech_r), this));
+	m_maincpu->space(AS_IO).install_read_handler(0x17, 0x17, 0, 0x0000, 0xff00, read8_delegate(FUNC(astrocde_state::votrax_speech_r), this));
 }
 
 
@@ -1718,7 +1721,7 @@ DRIVER_INIT_MEMBER(astrocde_state,gorf)
 	m_video_config = AC_SOUND_PRESENT | AC_LIGHTPEN_INTS | AC_STARS;
 	m_maincpu->space(AS_IO).install_read_handler(0x15, 0x15, 0, 0xf000, 0x0f00, read8_delegate(FUNC(astrocde_state::gorf_io_1_r), this));
 	m_maincpu->space(AS_IO).install_read_handler(0x16, 0x16, 0, 0xf000, 0x0f00, read8_delegate(FUNC(astrocde_state::gorf_io_2_r), this));
-	m_maincpu->space(AS_IO).install_read_handler(0x17, 0x17, 0, 0x0000, 0xff00, read8_delegate(FUNC(astrocde_state::gorf_speech_r), this));
+	m_maincpu->space(AS_IO).install_read_handler(0x17, 0x17, 0, 0x0000, 0xff00, read8_delegate(FUNC(astrocde_state::votrax_speech_r), this));
 }
 
 
diff --git a/src/mame/drivers/atarittl.cpp b/src/mame/drivers/atarittl.cpp
index 8945f97..061baad 100644
--- a/src/mame/drivers/atarittl.cpp
+++ b/src/mame/drivers/atarittl.cpp
@@ -1,5 +1,5 @@
 // license:BSD-3-Clause
-// copyright-holders:Fabio Priuli, Scott Stone
+// copyright-holders:Fabio Priuli, Scott Stone, Couriersud
 /***************************************************************************
 
  Atari / Kee Games Driver - Discrete Games made in the 1970's
@@ -53,6 +53,19 @@
  TM-018                   Dodgeball/Dodgem (Not Produced/Released) (1975)
  TM-024                   Qwakers (Not Produced/Released) (1974?) (Kee Games clone of Qwak!?)
 
+ - Information (current as of 21 Dec. 2016) on what logic chips (and some analog parts) are still needed to be emulated in the
+   netlist system per-game:
+
+ TM-057 (Stunt Cycle)
+    4136  Quad General-Purpose Operational Amplifiers
+
+ TM-055 (Indy 4)
+    7406  Hex Inverter Buffers/Drivers with O.C. H.V. Outputs (note: Might not be needed, could just clone from 7404)
+    7414  Hex Schmitt-Trigger Inverters
+    7417  Hex Buffers/Drivers
+    74164 8-bit Serial-In, Parallel-Out Shift Register
+    9301  1-of-10 Decoder
+    LM339 Quad Comparator
 
 ***************************************************************************/
 
@@ -136,7 +149,6 @@ void atarikee_state::video_start()
 
 
 static MACHINE_CONFIG_START( atarikee, atarikee_state )
-
 	/* basic machine hardware */
 	MCFG_DEVICE_ADD("maincpu", NETLIST_CPU, NETLIST_CLOCK)
 	MCFG_NETLIST_SETUP(atarikee)
diff --git a/src/mame/drivers/atlantis.cpp b/src/mame/drivers/atlantis.cpp
index f3e62c7..1a4f43e 100644
--- a/src/mame/drivers/atlantis.cpp
+++ b/src/mame/drivers/atlantis.cpp
@@ -38,6 +38,8 @@
 #include "machine/idectrl.h"
 #include "machine/midwayic.h"
 #include "machine/ins8250.h"
+#include "bus/rs232/rs232.h"
+#include "machine/terminal.h"
 #include "audio/dcs.h"
 #include "machine/pci.h"
 #include "machine/vrc4373.h"
@@ -64,8 +66,8 @@
 #define GALILEO_IRQ_SHIFT   1
 #define ZEUS_IRQ_SHIFT      2
 #define PARALLEL_IRQ_SHIFT  3
-#define UART0_SHIFT         4
-#define UART1_SHIFT         5
+#define UART1_SHIFT         4
+#define UART2_SHIFT         5
 #define VBLANK_IRQ_SHIFT    7
 
 /* static interrupts */
@@ -73,6 +75,7 @@
 #define VBLANK_IRQ_NUM          MIPS3_IRQ3
 #define IDE_IRQ_NUM             MIPS3_IRQ4
 
+#define DEBUG_CONSOLE   (0)
 #define LOG_RTC         (0)
 #define LOG_PORT        (0)
 #define LOG_IRQ         (0)
@@ -90,6 +93,7 @@ public:
 		m_ioasic(*this, "ioasic"),
 		m_uart0(*this, "uart0"),
 		m_uart1(*this, "uart1"),
+		m_uart2(*this, "uart2"),
 		m_rtc(*this, "rtc")
 	{ }
 	DECLARE_DRIVER_INIT(mwskins);
@@ -102,8 +106,9 @@ public:
 	required_device<zeus2_device> m_zeus;
 	required_device<dcs_audio_device> m_dcs;
 	required_device<midway_ioasic_device> m_ioasic;
-	required_device<ns16550_device> m_uart0;
+	optional_device<generic_terminal_device> m_uart0;
 	required_device<ns16550_device> m_uart1;
+	required_device<ns16550_device> m_uart2;
 	required_device<nvram_device> m_rtc;
 	uint8_t m_rtc_data[0x8000];
 
@@ -142,8 +147,8 @@ public:
 	DECLARE_WRITE_LINE_MEMBER(ide_irq);
 	DECLARE_WRITE_LINE_MEMBER(ioasic_irq);
 
-	DECLARE_WRITE_LINE_MEMBER(uart0_irq_callback);
 	DECLARE_WRITE_LINE_MEMBER(uart1_irq_callback);
+	DECLARE_WRITE_LINE_MEMBER(uart2_irq_callback);
 
 	DECLARE_CUSTOM_INPUT_MEMBER(port_mod_r);
 	DECLARE_READ32_MEMBER(port_ctrl_r);
@@ -186,7 +191,7 @@ READ32_MEMBER(atlantis_state::board_ctrl_r)
 	switch (newOffset) {
 	case CTRL_STATUS:
 		if (1 && m_screen->vblank())
-			data |= 0x80;
+			data |= 1 << VBLANK_IRQ_SHIFT;
 		if (m_last_offset != (newOffset | 0x40000))
 			if (LOG_IRQ)
 				logerror("%s:board_ctrl_r read from CTRL_STATUS offset %04X = %08X & %08X bus offset = %08X\n", machine().describe_context(), newOffset, data, mem_mask, offset);
@@ -371,7 +376,7 @@ WRITE32_MEMBER(atlantis_state::status_leds_w)
 			}
 			//popmessage("LED: %c", digit);
 			osd_printf_debug("%06X: status_leds_w digit: %c %08x = %02x\n", machine().device("maincpu")->safe_pc(), digit, offset, data);
-			logerror("%06X: status_leds_w digit: %c %08x = %02x\n", machine().device("maincpu")->safe_pc(), digit, offset, data);
+			if (0) logerror("%06X: status_leds_w digit: %c %08x = %02x\n", machine().device("maincpu")->safe_pc(), digit, offset, data);
 		}
 	}
 }
@@ -414,11 +419,11 @@ READ32_MEMBER(atlantis_state::user_io_input)
 }
 
 /*************************************
-*  UART0 interrupt handler
+*  UART1 interrupt handler
 *************************************/
-WRITE_LINE_MEMBER(atlantis_state::uart0_irq_callback)
+WRITE_LINE_MEMBER(atlantis_state::uart1_irq_callback)
 {
-	uint32_t status_bit = (1 << UART0_SHIFT);
+	uint32_t status_bit = (1 << UART1_SHIFT);
 	if (state && !(board_ctrl[CTRL_STATUS] & status_bit)) {
 		board_ctrl[CTRL_STATUS] |= status_bit;
 		update_asic_irq();
@@ -428,15 +433,15 @@ WRITE_LINE_MEMBER(atlantis_state::uart0_irq_callback)
 		board_ctrl[CTRL_CAUSE] &= ~status_bit;
 		update_asic_irq();
 	}
-	logerror("atlantis_state::uart0_irq_callback state = %1x\n", state);
+	logerror("atlantis_state::uart1_irq_callback state = %1x\n", state);
 }
 
 /*************************************
-*  UART1 interrupt handler
+*  UART2 interrupt handler
 *************************************/
-WRITE_LINE_MEMBER(atlantis_state::uart1_irq_callback)
+WRITE_LINE_MEMBER(atlantis_state::uart2_irq_callback)
 {
-	uint32_t status_bit = (1 << UART1_SHIFT);
+	uint32_t status_bit = (1 << UART2_SHIFT);
 	if (state && !(board_ctrl[CTRL_STATUS] & status_bit)) {
 		board_ctrl[CTRL_STATUS] |= status_bit;
 		update_asic_irq();
@@ -446,7 +451,7 @@ WRITE_LINE_MEMBER(atlantis_state::uart1_irq_callback)
 		board_ctrl[CTRL_CAUSE] &= ~status_bit;
 		update_asic_irq();
 	}
-	logerror("atlantis_state::uart1_irq_callback state = %1x\n", state);
+	logerror("atlantis_state::uart2_irq_callback state = %1x\n", state);
 }
 
 /*************************************
@@ -639,8 +644,8 @@ void atlantis_state::machine_reset()
  *************************************/
 static ADDRESS_MAP_START( map0, AS_PROGRAM, 32, atlantis_state )
 	AM_RANGE(0x00000000, 0x0001ffff) AM_READWRITE8(cmos_r, cmos_w, 0xff)
-	AM_RANGE(0x00100000, 0x0010001f) AM_DEVREADWRITE8("uart0", ns16550_device, ins8250_r, ins8250_w, 0xff) // Serial UART0 (TL16C552 CS0)
-	AM_RANGE(0x00180000, 0x0018001f) AM_DEVREADWRITE8("uart1", ns16550_device, ins8250_r, ins8250_w, 0xff) // Serial UART1 (TL16C552 CS1)
+	AM_RANGE(0x00100000, 0x0010001f) AM_DEVREADWRITE8("uart1", ns16550_device, ins8250_r, ins8250_w, 0xff) // Serial UART1 (TL16C552 CS0)
+	AM_RANGE(0x00180000, 0x0018001f) AM_DEVREADWRITE8("uart2", ns16550_device, ins8250_r, ins8250_w, 0xff) // Serial UART2 (TL16C552 CS1)
 	//AM_RANGE(0x00200000, 0x0020001f) // Parallel UART (TL16C552 CS2)
 	AM_RANGE(0x00400000, 0x004000bf) AM_READWRITE8(blue_r, blue_w, 0xff)
 	AM_RANGE(0x00880000, 0x00c80003) AM_READWRITE(board_ctrl_r, board_ctrl_w)
@@ -799,6 +804,17 @@ static INPUT_PORTS_START( mwskins )
 
 INPUT_PORTS_END
 
+#if 0
+static DEVICE_INPUT_DEFAULTS_START(mwskins_comm)
+	DEVICE_INPUT_DEFAULTS("RS232_TXBAUD", 0xff, RS232_BAUD_14400)
+	DEVICE_INPUT_DEFAULTS("RS232_RXBAUD", 0xff, RS232_BAUD_14400)
+	DEVICE_INPUT_DEFAULTS("RS232_STARTBITS", 0xff, RS232_STARTBITS_1)
+	DEVICE_INPUT_DEFAULTS("RS232_DATABITS", 0xff, RS232_DATABITS_8)
+	DEVICE_INPUT_DEFAULTS("RS232_PARITY", 0xff, RS232_PARITY_NONE)
+	DEVICE_INPUT_DEFAULTS("RS232_STOPBITS", 0xff, RS232_STOPBITS_1)
+DEVICE_INPUT_DEFAULTS_END
+#endif
+
 /*************************************
  *
  *  Machine driver
@@ -843,8 +859,8 @@ static MACHINE_CONFIG_START( mwskins, atlantis_state )
 	/* sound hardware */
 	//MCFG_DEVICE_ADD("dcs", DCS2_AUDIO_DSIO, 0)
 	MCFG_DEVICE_ADD("dcs", DCS2_AUDIO_DENVER, 0)
-	MCFG_DCS2_AUDIO_DRAM_IN_MB(4)
-	MCFG_DCS2_AUDIO_POLLING_OFFSET(0) /* no place to hook :-( */
+	MCFG_DCS2_AUDIO_DRAM_IN_MB(8)
+	//MCFG_DCS2_AUDIO_POLLING_OFFSET(0) /* no place to hook :-( */
 
 	MCFG_DEVICE_ADD("ioasic", MIDWAY_IOASIC, 0)
 	MCFG_MIDWAY_IOASIC_SHUFFLE(MIDWAY_IOASIC_STANDARD)
@@ -852,17 +868,42 @@ static MACHINE_CONFIG_START( mwskins, atlantis_state )
 	MCFG_MIDWAY_IOASIC_UPPER(325)
 	MCFG_MIDWAY_IOASIC_IRQ_CALLBACK(WRITELINE(atlantis_state, ioasic_irq))
 	MCFG_MIDWAY_IOASIC_AUTO_ACK(1)
+	if DEBUG_CONSOLE {
+		MCFG_MIDWAY_IOASIC_OUT_TX_CB(DEVWRITE8("uart0", generic_terminal_device, write))
+		MCFG_DEVICE_ADD("uart0", GENERIC_TERMINAL, 0)
+		MCFG_GENERIC_TERMINAL_KEYBOARD_CB(DEVWRITE8("ioasic", midway_ioasic_device, serial_rx_w))
+	}
 
 	// TL16C552 UART
-	MCFG_DEVICE_ADD("uart0", NS16550, XTAL_24MHz)
-	MCFG_INS8250_OUT_INT_CB(DEVWRITELINE(":", atlantis_state, uart0_irq_callback))
 	MCFG_DEVICE_ADD("uart1", NS16550, XTAL_24MHz)
-	MCFG_INS8250_OUT_INT_CB(DEVWRITELINE(":", atlantis_state, uart1_irq_callback))
-
+	//MCFG_INS8250_OUT_TX_CB(DEVWRITELINE("com1", rs232_port_device, write_txd))
+	//MCFG_INS8250_OUT_DTR_CB(DEVWRITELINE("com1", rs232_port_device, write_dtr))
+	//MCFG_INS8250_OUT_RTS_CB(DEVWRITELINE("com1", rs232_port_device, write_rts))
+	//MCFG_INS8250_OUT_INT_CB(DEVWRITELINE(":", atlantis_state, uart1_irq_callback))
+
+	MCFG_DEVICE_ADD("uart2", NS16550, XTAL_24MHz)
+	//MCFG_INS8250_OUT_TX_CB(DEVWRITELINE("com2", rs232_port_device, write_txd))
+	//MCFG_INS8250_OUT_DTR_CB(DEVWRITELINE("com2", rs232_port_device, write_dtr))
+	//MCFG_INS8250_OUT_RTS_CB(DEVWRITELINE("com2", rs232_port_device, write_rts))
+	//MCFG_INS8250_OUT_INT_CB(DEVWRITELINE(":", atlantis_state, uart2_irq_callback))
+
+	//MCFG_RS232_PORT_ADD("com1", default_rs232_devices, nullptr)
+	//MCFG_RS232_RXD_HANDLER(DEVWRITELINE("uart1", ins8250_uart_device, rx_w))
+	//MCFG_RS232_DCD_HANDLER(DEVWRITELINE("uart1", ins8250_uart_device, dcd_w))
+	//MCFG_RS232_DSR_HANDLER(DEVWRITELINE("uart1", ins8250_uart_device, dsr_w))
+	//MCFG_RS232_RI_HANDLER(DEVWRITELINE("uart1", ins8250_uart_device, ri_w))
+	//MCFG_RS232_CTS_HANDLER(DEVWRITELINE("uart1", ins8250_uart_device, cts_w))
+	//MCFG_DEVICE_CARD_DEVICE_INPUT_DEFAULTS("com1", mwskins_comm)
+
+	//MCFG_RS232_PORT_ADD("com2", default_rs232_devices, nullptr)
+	//MCFG_RS232_RXD_HANDLER(DEVWRITELINE("uart2", ins8250_uart_device, rx_w))
+	//MCFG_RS232_DCD_HANDLER(DEVWRITELINE("uart2", ins8250_uart_device, dcd_w))
+	//MCFG_RS232_DSR_HANDLER(DEVWRITELINE("uart2", ins8250_uart_device, dsr_w))
+	//MCFG_RS232_RI_HANDLER(DEVWRITELINE("uart2", ins8250_uart_device, ri_w))
+	//MCFG_RS232_CTS_HANDLER(DEVWRITELINE("uart2", ins8250_uart_device, cts_w))
 MACHINE_CONFIG_END
 
 
-
 /*************************************
  *
  *  ROM definition(s)
diff --git a/src/mame/drivers/attckufo.cpp b/src/mame/drivers/attckufo.cpp
index 8d03c8f..3c826af 100644
--- a/src/mame/drivers/attckufo.cpp
+++ b/src/mame/drivers/attckufo.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /***************************************************************************
 
diff --git a/src/mame/drivers/aussiebyte.cpp b/src/mame/drivers/aussiebyte.cpp
index 97f1da8..aa4aa96 100644
--- a/src/mame/drivers/aussiebyte.cpp
+++ b/src/mame/drivers/aussiebyte.cpp
@@ -17,7 +17,6 @@
     - Hard drive controllers and drives
     - Test Centronics printer
     - PIO connections
-    - RTC not working
 
     Note of MAME restrictions:
     - Votrax doesn't sound anything like the real thing
@@ -76,7 +75,7 @@ static ADDRESS_MAP_START( aussiebyte_io, AS_IO, 8, aussiebyte_state )
 	AM_RANGE(0x35, 0x35) AM_WRITE(port35_w) // data to vram and aram
 	AM_RANGE(0x36, 0x36) AM_READ(port36_r) // data from vram and aram
 	AM_RANGE(0x37, 0x37) AM_READ(port37_r) // read dispen flag
-	AM_RANGE(0x40, 0x4f) AM_DEVREADWRITE("rtc", msm5832_device, data_r, data_w)
+	AM_RANGE(0x40, 0x4f) AM_READWRITE(rtc_r, rtc_w)
 ADDRESS_MAP_END
 
 /***********************************************************
@@ -224,6 +223,32 @@ READ8_MEMBER( aussiebyte_state::port28_r )
 
 /***********************************************************
 
+    RTC
+
+************************************************************/
+READ8_MEMBER( aussiebyte_state::rtc_r )
+{
+	m_rtc->cs_w(1);
+	m_rtc->read_w(1);
+	m_rtc->address_w(offset);
+	uint8_t data = m_rtc->data_r(space,0);
+	m_rtc->read_w(0);
+	m_rtc->cs_w(0);
+	return data;
+}
+
+WRITE8_MEMBER( aussiebyte_state::rtc_w )
+{
+	m_rtc->cs_w(1);
+	m_rtc->address_w(offset);
+	m_rtc->data_w(space,0,data);
+	m_rtc->write_w(1);
+	m_rtc->write_w(0);
+	m_rtc->cs_w(0);
+}
+
+/***********************************************************
+
     DMA
 
 ************************************************************/
diff --git a/src/mame/drivers/beezer.cpp b/src/mame/drivers/beezer.cpp
index ce5630b..cc6e0a5 100644
--- a/src/mame/drivers/beezer.cpp
+++ b/src/mame/drivers/beezer.cpp
@@ -1,57 +1,186 @@
-// license:BSD-3-Clause
-// copyright-holders:Mathis Rosenhauer
-/*
+// license: BSD-3-Clause
+// copyright-holders: Mathis Rosenhauer, Dirk Best
+// thanks-to: Jonathan Gevaryahu
+/***************************************************************************
+
+    Beezer
 
-  Beezer - (c) 1982 Tong Electronic
+    (c) 1982 Tong Electronic
 
-  Written by Mathis Rosenhauer
+    Notes:
+    - To enter test mode, hold down 1P Start and 2P Start, then reset
+    - One of the ROMs contains a message that this game was created
+      by "Pacific Polytechnical Corporation, Santa Cruz"
 
-  TODO:
-  - what's really wrong with the sound? Any reference available?
+    TODO:
+    - Improve sound (filters? A reference recording would be nice)
+    - Schematics in the sound area seem incomplete, there are
+      several unknown connections
+    - Watchdog timing (controlled by a 555)
+    - Figure out differences between the two sets (test mode isn't
+      working in beezer1, instruction screen is different)
+    - Verify accuracy of colors
 
-*/
+***************************************************************************/
 
 #include "emu.h"
-#include "machine/6522via.h"
 #include "cpu/m6809/m6809.h"
-#include "includes/beezer.h"
+#include "machine/input_merger.h"
+#include "machine/watchdog.h"
+#include "machine/bankdev.h"
+#include "machine/6522via.h"
+#include "machine/6840ptm.h"
+#include "sound/mm5837.h"
+#include "sound/dac76.h"
+#include "video/resnet.h"
+
+
+//**************************************************************************
+//  TYPE DEFINITIONS
+//**************************************************************************
+
+class beezer_state : public driver_device
+{
+public:
+	beezer_state(const machine_config &mconfig, device_type type, const char *tag)
+		: driver_device(mconfig, type, tag),
+		m_maincpu(*this, "maincpu"),
+		m_sysbank(*this, "sysbank"),
+		m_banked_roms(*this, "banked"),
+		m_rombank{ {*this, "rombank_f1"}, {*this, "rombank_f3"}, {*this, "rombank_e1"}, {*this, "rombank_e3"}, {*this, "rombank_e5"}, {*this, "rombank_f5"}, {*this, "rombank_f7"} },
+		m_via_system(*this, "via_u6"),
+		m_screen(*this, "screen"),
+		m_palette(*this, "palette"),
+		m_videoram(*this, "videoram"),
+		m_audiocpu(*this, "audiocpu"),
+		m_via_audio(*this, "via_u18"),
+		m_ptm(*this, "ptm"),
+		m_dac(*this, "dac"),
+		m_timer_count(nullptr),
+		m_count(0), m_noise(0),
+		m_pbus(0xff), m_x(0), m_y(0), m_z(0)
+	{
+		m_ch_sign[0] = m_ch_sign[1] = m_ch_sign[2] = m_ch_sign[3] = 0;
+		m_dac_data[0] = m_dac_data[1] = m_dac_data[2] = m_dac_data[3] = 0;
+	}
+
+	TIMER_DEVICE_CALLBACK_MEMBER(scanline_cb);
+	uint32_t screen_update_beezer(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
+	DECLARE_PALETTE_INIT(beezer);
+	DECLARE_WRITE8_MEMBER(palette_w);
+	DECLARE_READ8_MEMBER(line_r);
+
+	DECLARE_WRITE_LINE_MEMBER(noise_w);
+	DECLARE_WRITE8_MEMBER(dac_w);
+	DECLARE_READ8_MEMBER(via_audio_pa_r);
+	DECLARE_WRITE8_MEMBER(via_audio_pa_w);
+	DECLARE_WRITE8_MEMBER(via_audio_pb_w);
+	DECLARE_WRITE_LINE_MEMBER(ptm_out0_w);
+	DECLARE_WRITE_LINE_MEMBER(ptm_out1_w);
+	DECLARE_WRITE_LINE_MEMBER(ptm_out2_w);
+	DECLARE_WRITE_LINE_MEMBER(dmod_clr_w);
+	DECLARE_WRITE_LINE_MEMBER(dmod_data_w);
+
+	DECLARE_READ8_MEMBER(via_system_pa_r);
+	DECLARE_READ8_MEMBER(via_system_pb_r);
+	DECLARE_WRITE8_MEMBER(via_system_pa_w);
+	DECLARE_WRITE8_MEMBER(via_system_pb_w);
+	DECLARE_WRITE8_MEMBER(bankswitch_w);
+
+protected:
+	virtual void machine_start() override;
+	virtual void machine_reset() override;
+	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+
+private:
+	required_device<cpu_device> m_maincpu;
+	required_device<address_map_bank_device> m_sysbank;
+	required_memory_region m_banked_roms;
+	required_memory_bank m_rombank[7];
+	required_device<via6522_device> m_via_system;
+	required_device<screen_device> m_screen;
+	required_device<palette_device> m_palette;
+	required_shared_ptr<uint8_t> m_videoram;
+	required_device<cpu_device> m_audiocpu;
+	required_device<via6522_device> m_via_audio;
+	required_device<ptm6840_device> m_ptm;
+	required_device<dac76_device> m_dac;
+
+	double m_weights_r[3];
+	double m_weights_g[3];
+	double m_weights_b[2];
+
+	emu_timer *m_timer_count;
+
+	int m_ch_sign[4];
+	uint8_t m_dac_data[4];
+	int m_count;
+	int m_noise;
+
+	uint8_t m_pbus;
+	int m_x, m_y, m_z;
+};
+
+
+//**************************************************************************
+//  ADDRESS MAPS
+//**************************************************************************
 
 static ADDRESS_MAP_START( main_map, AS_PROGRAM, 8, beezer_state )
 	AM_RANGE(0x0000, 0xbfff) AM_RAM AM_SHARE("videoram")
-	AM_RANGE(0xc000, 0xcfff) AM_ROMBANK("bank1")
-	AM_RANGE(0xd000, 0xdfff) AM_ROM AM_WRITE(beezer_bankswitch_w) // ROM at G1, bankswitch
-	AM_RANGE(0xe000, 0xffff) AM_ROM // ROMS at G3, G5
+	AM_RANGE(0xc000, 0xcfff) AM_DEVICE("sysbank", address_map_bank_device, amap8)
+	AM_RANGE(0xd000, 0xdfff) AM_ROM AM_REGION("maincpu", 0x0000) AM_WRITE(bankswitch_w) // g1
+	AM_RANGE(0xe000, 0xefff) AM_ROM AM_REGION("maincpu", 0x1000) // g3
+	AM_RANGE(0xf000, 0xffff) AM_ROM AM_REGION("maincpu", 0x2000) // g5
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( banked_map, AS_PROGRAM, 8, beezer_state )
+	AM_RANGE(0x0600, 0x0600) AM_MIRROR(0x1ff) AM_DEVWRITE("watchdog", watchdog_timer_device, reset_w)
+	AM_RANGE(0x0800, 0x080f) AM_MIRROR(0x1f0) AM_WRITE(palette_w)
+	AM_RANGE(0x0a00, 0x0a00) AM_MIRROR(0x1ff) AM_READ(line_r)
+	AM_RANGE(0x0e00, 0x0e0f) AM_MIRROR(0x1f0) AM_DEVREADWRITE("via_u6", via6522_device, read, write)
+	AM_RANGE(0x1000, 0x1fff) AM_ROMBANK("rombank_f1")
+	AM_RANGE(0x2000, 0x2fff) AM_ROMBANK("rombank_f3")
+	AM_RANGE(0x3000, 0x3fff) AM_ROMBANK("rombank_e1")
+	AM_RANGE(0x4000, 0x4fff) AM_ROMBANK("rombank_e3")
+	AM_RANGE(0x5000, 0x5fff) AM_ROMBANK("rombank_e5")
+	AM_RANGE(0x6000, 0x6fff) AM_ROMBANK("rombank_f5")
+	AM_RANGE(0x7000, 0x7fff) AM_ROMBANK("rombank_f7")
 ADDRESS_MAP_END
 
 static ADDRESS_MAP_START( sound_map, AS_PROGRAM, 8, beezer_state )
-	AM_RANGE(0x0000, 0x07ff) AM_RAM // RAM at 0D
-	AM_RANGE(0x0800, 0x0fff) AM_RAM // optional RAM at 2D (can be rom here instead)
-	AM_RANGE(0x1000, 0x1007) AM_MIRROR(0x07f8) AM_DEVREADWRITE("custom", beezer_sound_device, sh6840_r, sh6840_w)
-	AM_RANGE(0x1800, 0x180F) AM_MIRROR(0x07f0) AM_DEVREADWRITE("via6522_1", via6522_device, read, write)
-	AM_RANGE(0x8000, 0x8003) AM_MIRROR(0x1ffc) AM_DEVWRITE("custom", beezer_sound_device, sfxctrl_w)
-	//AM_RANGE(0xa000, 0xbfff) AM_ROM // ROM at 2D (can be ram here instead), unpopulated
-	//AM_RANGE(0xc000, 0xdfff) AM_ROM // ROM at 4D, unpopulated
-	AM_RANGE(0xe000, 0xffff) AM_ROM // ROM at 6D
+	AM_RANGE(0x0000, 0x07ff) AM_RAM // 0d
+	AM_RANGE(0x0800, 0x0fff) AM_RAM // 2d, optional (can be rom)
+	AM_RANGE(0x1000, 0x1007) AM_MIRROR(0x07f8) AM_DEVREADWRITE("ptm", ptm6840_device, read, write)
+	AM_RANGE(0x1800, 0x180f) AM_MIRROR(0x07f0) AM_DEVREADWRITE("via_u18", via6522_device, read, write)
+	AM_RANGE(0x8000, 0x8003) AM_MIRROR(0x1ffc) AM_WRITE(dac_w)
+//  AM_RANGE(0xa000, 0xbfff) AM_ROM // 2d (can be ram, unpopulated)
+//  AM_RANGE(0xc000, 0xdfff) AM_ROM // 4d (unpopulated)
+	AM_RANGE(0xe000, 0xffff) AM_ROM AM_REGION("audiocpu", 0) // 6d
 ADDRESS_MAP_END
 
 
+//**************************************************************************
+//  INPUTS
+//**************************************************************************
+
 static INPUT_PORTS_START( beezer )
 	PORT_START("IN0")
 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_TILT )
 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN1 )
 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_START2 )
 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START1 )
-	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
-	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
-	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
-	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
+	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED )
+	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
+	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
+	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
 
 	PORT_START("IN1")
 	PORT_BIT( 0x0f, 0x00, IPT_TRACKBALL_X ) PORT_SENSITIVITY(20) PORT_KEYDELTA(10) PORT_REVERSE
 	PORT_START("IN2")
 	PORT_BIT( 0x0f, 0x00, IPT_TRACKBALL_Y ) PORT_SENSITIVITY(20) PORT_KEYDELTA(10) PORT_REVERSE
 
-	/* Manual says "Dip Switch A" is not used. */
+	// DSWA isn't populated on the board and is pulled to 0xff with a resistor pack
 	PORT_START("DSWA")
 	PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
 
@@ -78,23 +207,281 @@ static INPUT_PORTS_START( beezer )
 	PORT_DIPSETTING(    0x00, DEF_STR( Hardest ) )
 INPUT_PORTS_END
 
+
+//**************************************************************************
+//  VIDEO EMULATION
+//**************************************************************************
+
+TIMER_DEVICE_CALLBACK_MEMBER( beezer_state::scanline_cb )
+{
+	// TDISP, each 32 lines
+	m_via_system->write_ca2((param & 32) ? 1 : 0);
+
+	// actually unused by the game (points to a tight loop)
+	if (param == 240)
+		m_maincpu->set_input_line(M6809_FIRQ_LINE, ASSERT_LINE);
+	else
+		m_maincpu->set_input_line(M6809_FIRQ_LINE, CLEAR_LINE);
+}
+
+uint32_t beezer_state::screen_update_beezer(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
+{
+	for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
+	{
+		for (int x = cliprect.min_x; x <= cliprect.max_x; x += 2)
+		{
+			bitmap.pix16(y, x + 1) = m_videoram[0x80 * x + y] & 0x0f;
+			bitmap.pix16(y, x + 0) = m_videoram[0x80 * x + y] >> 4;
+		}
+	}
+
+	return 0;
+}
+
+PALETTE_INIT_MEMBER(beezer_state, beezer)
+{
+	const int resistances_rg[3] = { 1200, 560, 330 };
+	const int resistances_b[2]  = { 560, 330 };
+
+	// calculate coefficients for later use
+	compute_resistor_weights(0, 255, -1.0,
+		3, resistances_rg, m_weights_r, 680, 150,
+		3, resistances_rg, m_weights_g, 680, 150,
+		2, resistances_b,  m_weights_b, 680, 150);
+}
+
+WRITE8_MEMBER( beezer_state::palette_w )
+{
+	int r = combine_3_weights(m_weights_r, BIT(data, 0), BIT(data, 1), BIT(data, 2));
+	int g = combine_3_weights(m_weights_g, BIT(data, 3), BIT(data, 4), BIT(data, 5));
+	int b = combine_2_weights(m_weights_b, BIT(data, 6), BIT(data, 7));
+
+	m_palette->set_pen_color(offset, rgb_t(r, g, b));
+}
+
+READ8_MEMBER( beezer_state::line_r )
+{
+	// d2 to d7 connected to hex buffer u34
+	return m_screen->vpos() & 0xfc;
+}
+
+
+//**************************************************************************
+//  AUDIO
+//**************************************************************************
+
+void beezer_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+	// channel multiplexer at u52
+	int ch = m_count++ & 3;
+
+	m_dac->update();
+
+	m_dac->b1_w(BIT(m_dac_data[ch], 6));
+	m_dac->b2_w(BIT(m_dac_data[ch], 5));
+	m_dac->b3_w(BIT(m_dac_data[ch], 4));
+	m_dac->b4_w(BIT(m_dac_data[ch], 3));
+	m_dac->b5_w(BIT(m_dac_data[ch], 2));
+	m_dac->b6_w(BIT(m_dac_data[ch], 1));
+	m_dac->b7_w(BIT(m_dac_data[ch], 0));
+
+	m_dac->sb_w(m_ch_sign[ch] ^ BIT(m_dac_data[ch], 7));
+}
+
+WRITE_LINE_MEMBER( beezer_state::noise_w )
+{
+	m_noise = state;
+	m_via_audio->write_pb6(m_noise);
+}
+
+WRITE8_MEMBER( beezer_state::dac_w )
+{
+	m_dac_data[offset] = data;
+}
+
+READ8_MEMBER( beezer_state::via_audio_pa_r )
+{
+	return m_pbus;
+}
+
+WRITE8_MEMBER( beezer_state::via_audio_pa_w )
+{
+	m_pbus = data;
+}
+
+WRITE8_MEMBER( beezer_state::via_audio_pb_w )
+{
+	// bit 0 - dmod disable
+	// bit 1 - fm or am
+	// bit 2 - am
+	// bit 3 - fmsel0
+	// bit 4 - fmsel1
+	// -- above bits not handled and only partially visible on the schematic
+
+	// bit 7 - noise gate on rising edge to ptm c1
+	if (m_ch_sign[0] == 0 && (BIT(data, 7) == 1))
+		m_ptm->set_c1(m_noise);
+
+	m_ch_sign[0] = BIT(data, 7);
+}
+
+WRITE_LINE_MEMBER( beezer_state::ptm_out0_w )
+{
+	m_ch_sign[1] = state;
+}
+
+WRITE_LINE_MEMBER( beezer_state::ptm_out1_w )
+{
+	// on rising edge, enable noise input to ptm c3
+	if (m_ch_sign[2] == 0 && state == 1)
+		m_ptm->set_c3(m_noise);
+
+	m_ch_sign[2] = state;
+}
+
+WRITE_LINE_MEMBER( beezer_state::ptm_out2_w )
+{
+	m_ch_sign[3] = state;
+}
+
+WRITE_LINE_MEMBER( beezer_state::dmod_clr_w )
+{
+	// schematics don't show where this is connected
+}
+
+WRITE_LINE_MEMBER( beezer_state::dmod_data_w )
+{
+	// schematics don't show where this is connected
+}
+
+
+//**************************************************************************
+//  MACHINE EMULATION
+//**************************************************************************
+
+READ8_MEMBER( beezer_state::via_system_pa_r )
+{
+	uint8_t data = 0;
+
+	data |= 1 << 4; // N/C
+	data |= m_z << 5;
+	data |= m_y << 6;
+	data |= m_x << 7;
+
+	return data;
+}
+
+WRITE8_MEMBER(beezer_state::via_system_pa_w)
+{
+	// bit 3, audio cpu reset line
+	m_audiocpu->set_input_line(INPUT_LINE_RESET, BIT(data, 3) ? CLEAR_LINE : ASSERT_LINE);
+
+	// bit 2, enable for ls139
+	if (BIT(data, 2) == 0)
+	{
+		// bit 0-1, input selection
+		switch (data & 0x03)
+		{
+		case 0:
+			m_pbus = ioport("IN0")->read();
+			break;
+		case 1:
+			m_pbus = ioport("IN1")->read() | (ioport("IN2")->read() << 4);
+			break;
+		case 2:
+			m_pbus = ioport("DSWB")->read();
+			break;
+		case 3:
+			m_pbus = ioport("DSWA")->read();
+			break;
+		}
+	}
+}
+
+READ8_MEMBER( beezer_state::via_system_pb_r )
+{
+	return m_pbus;
+}
+
+WRITE8_MEMBER( beezer_state::via_system_pb_w )
+{
+	m_pbus = data;
+}
+
+WRITE8_MEMBER( beezer_state::bankswitch_w )
+{
+	m_x = BIT(data, 3);
+	m_y = BIT(data, 4);
+	m_z = BIT(data, 5);
+
+	m_sysbank->set_bank(data & 0x07);
+
+	for (int i = 0; i < 7; i++)
+		m_rombank[i]->set_entry(m_x);
+}
+
 void beezer_state::machine_start()
 {
+	// configure rom banks
+	for (int i = 0; i < 7; i++)
+		m_rombank[i]->configure_entries(0, 2, m_banked_roms->base() + (i * 0x2000), 0x1000);
+
+	// allocate timers
+	m_timer_count = timer_alloc(0);
+
+	// register for state saving
+	save_pointer(NAME(m_ch_sign), 4);
+	save_pointer(NAME(m_dac_data), 4);
+	save_item(NAME(m_count));
+	save_item(NAME(m_noise));
+	save_item(NAME(m_pbus));
+	save_item(NAME(m_x));
+	save_item(NAME(m_y));
+	save_item(NAME(m_z));
 }
 
-static MACHINE_CONFIG_START( beezer, beezer_state )
+void beezer_state::machine_reset()
+{
+	m_pbus = 0xff;
+
+	// initialize memory banks
+	bankswitch_w(machine().dummy_space(), 0, 0);
+
+	// start timer
+	m_timer_count->adjust(attotime::zero, 0, attotime::from_hz((XTAL_12MHz / 12) / 16));
+}
 
-	/* basic machine hardware */
-	MCFG_CPU_ADD("maincpu", M6809, 1000000)        /* 1 MHz */
+
+//**************************************************************************
+//  MACHINE DEFINTIONS
+//**************************************************************************
+
+static MACHINE_CONFIG_START( beezer, beezer_state )
+	// basic machine hardware
+	MCFG_CPU_ADD("maincpu", M6809, XTAL_12MHz / 12)
 	MCFG_CPU_PROGRAM_MAP(main_map)
-	MCFG_TIMER_DRIVER_ADD_SCANLINE("scantimer", beezer_state, beezer_interrupt, "screen", 0, 1)
 
-	MCFG_CPU_ADD("audiocpu", M6809, 1000000)        /* 1 MHz */
-	MCFG_CPU_PROGRAM_MAP(sound_map)
+	MCFG_DEVICE_ADD("sysbank", ADDRESS_MAP_BANK, 0)
+	MCFG_DEVICE_PROGRAM_MAP(banked_map)
+	MCFG_ADDRESS_MAP_BANK_ENDIANNESS(ENDIANNESS_BIG)
+	MCFG_ADDRESS_MAP_BANK_DATABUS_WIDTH(8)
+	MCFG_ADDRESS_MAP_BANK_ADDRBUS_WIDTH(15)
+	MCFG_ADDRESS_MAP_BANK_STRIDE(0x1000)
+
+	MCFG_TIMER_DRIVER_ADD_SCANLINE("scantimer", beezer_state, scanline_cb, "screen", 0, 1)
+
+	MCFG_DEVICE_ADD("via_u6", VIA6522, 0)
+	MCFG_VIA6522_READPA_HANDLER(READ8(beezer_state, via_system_pa_r))
+	MCFG_VIA6522_READPB_HANDLER(READ8(beezer_state, via_system_pb_r))
+	MCFG_VIA6522_WRITEPA_HANDLER(WRITE8(beezer_state, via_system_pa_w))
+	MCFG_VIA6522_WRITEPB_HANDLER(WRITE8(beezer_state, via_system_pb_w))
+	MCFG_VIA6522_CB1_HANDLER(DEVWRITELINE("via_u18", via6522_device, write_ca2))
+	MCFG_VIA6522_CB2_HANDLER(DEVWRITELINE("via_u18", via6522_device, write_ca1))
+	MCFG_VIA6522_IRQ_HANDLER(INPUTLINE("maincpu", M6809_IRQ_LINE))
 
 	MCFG_WATCHDOG_ADD("watchdog")
 
-	/* video hardware */
+	// video hardware
 	MCFG_SCREEN_ADD("screen", RASTER)
 	MCFG_SCREEN_REFRESH_RATE(60)
 	MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500) /* not accurate */)
@@ -104,81 +491,109 @@ static MACHINE_CONFIG_START( beezer, beezer_state )
 	MCFG_SCREEN_PALETTE("palette")
 
 	MCFG_PALETTE_ADD("palette", 16)
+	MCFG_PALETTE_INIT_OWNER(beezer_state, beezer)
 
+	// sound hardware
+	MCFG_CPU_ADD("audiocpu", M6809, XTAL_12MHz / 12)
+	MCFG_CPU_PROGRAM_MAP(sound_map)
 
-	/* sound hardware */
-	MCFG_SPEAKER_STANDARD_MONO("speaker")
+	MCFG_INPUT_MERGER_ACTIVE_HIGH("audio_irqs")
+	MCFG_INPUT_MERGER_OUTPUT_HANDLER(INPUTLINE("audiocpu", M6809_IRQ_LINE))
+
+	MCFG_DEVICE_ADD("via_u18", VIA6522, 0)
+	MCFG_VIA6522_READPA_HANDLER(READ8(beezer_state, via_audio_pa_r))
+	MCFG_VIA6522_WRITEPA_HANDLER(WRITE8(beezer_state, via_audio_pa_w))
+	MCFG_VIA6522_WRITEPB_HANDLER(WRITE8(beezer_state, via_audio_pb_w))
+	MCFG_VIA6522_CA2_HANDLER(DEVWRITELINE("via_u6", via6522_device, write_cb1))
+	MCFG_VIA6522_CB1_HANDLER(WRITELINE(beezer_state, dmod_clr_w))
+	MCFG_VIA6522_CB2_HANDLER(WRITELINE(beezer_state, dmod_data_w))
+	MCFG_VIA6522_IRQ_HANDLER(DEVWRITELINE("audio_irqs", input_merger_active_high_device, in0_w))
+
+	MCFG_DEVICE_ADD("ptm", PTM6840, XTAL_12MHz / 12)
+	MCFG_PTM6840_OUT0_CB(WRITELINE(beezer_state, ptm_out0_w))
+	MCFG_PTM6840_OUT1_CB(WRITELINE(beezer_state, ptm_out1_w))
+	MCFG_PTM6840_OUT2_CB(WRITELINE(beezer_state, ptm_out2_w))
+	MCFG_PTM6840_IRQ_CB(DEVWRITELINE("audio_irqs", input_merger_active_high_device, in1_w))
+	// schematics show an input labeled VCO to channel 2, but the source is unknown
+
+	MCFG_MM5837_ADD("noise")
+	MCFG_MM5837_VDD(12)
+	MCFG_MM5837_OUTPUT_CB(WRITELINE(beezer_state, noise_w))
 
-	MCFG_SOUND_ADD("custom", BEEZER, 0)
+	MCFG_SPEAKER_STANDARD_MONO("speaker")
+	MCFG_SOUND_ADD("dac", DAC76, 0)
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "speaker", 1.0)
-
-	/* via */
-	MCFG_DEVICE_ADD("via6522_0", VIA6522, 0)
-	MCFG_VIA6522_READPA_HANDLER(READ8(beezer_state, b_via_0_pa_r))
-	MCFG_VIA6522_READPB_HANDLER(READ8(beezer_state, b_via_0_pb_r))
-	MCFG_VIA6522_WRITEPA_HANDLER(WRITE8(beezer_state, b_via_0_pa_w))
-	MCFG_VIA6522_WRITEPB_HANDLER(WRITE8(beezer_state, b_via_0_pb_w))
-	MCFG_VIA6522_CB2_HANDLER(DEVWRITELINE("via6522_1", via6522_device, write_ca1))
-	MCFG_VIA6522_IRQ_HANDLER(INPUTLINE("maincpu", M6809_IRQ_LINE))
-
-	MCFG_DEVICE_ADD("via6522_1", VIA6522, 0)
-	MCFG_VIA6522_READPA_HANDLER(READ8(beezer_state, b_via_1_pa_r))
-	MCFG_VIA6522_READPB_HANDLER(READ8(beezer_state, b_via_1_pb_r))
-	MCFG_VIA6522_WRITEPA_HANDLER(WRITE8(beezer_state, b_via_1_pa_w))
-	MCFG_VIA6522_WRITEPB_HANDLER(WRITE8(beezer_state, b_via_1_pb_w))
-	MCFG_VIA6522_CA2_HANDLER(DEVWRITELINE("via6522_0", via6522_device, write_cb1))
-	MCFG_VIA6522_IRQ_HANDLER(INPUTLINE("audiocpu", M6809_IRQ_LINE))
 MACHINE_CONFIG_END
 
-/***************************************************************************
-
-  Game driver(s)
 
-***************************************************************************/
+//**************************************************************************
+//  ROM DEFINITIONS
+//**************************************************************************
 
 ROM_START( beezer )
-	ROM_REGION( 0x20000, "maincpu", 0 )
-	ROM_LOAD( "g1",   0x0d000, 0x1000, CRC(3467a0ec) SHA1(0b094a9bf772b101acd26cf09009c67dd4785ed2) )
-	ROM_LOAD( "g3",   0x0e000, 0x1000, CRC(9950cdf2) SHA1(b2b59cc1080357de6ba297392881d626157df809) )
-	ROM_LOAD( "g5",   0x0f000, 0x1000, CRC(a4b09879) SHA1(69739dd1d3c88ee6ab310ca3c71b3b50d8ec618f) )
-
-	ROM_LOAD( "f1",   0x12000, 0x2000, CRC(ce1b0b8b) SHA1(8ed1d793928bb7afa041a4f61e0c2f78b4442f2f) )
-	ROM_LOAD( "f3",   0x14000, 0x2000, CRC(6a11072a) SHA1(9700beaec669849da4d0e39d6dbf0b872d7f1b7f) )
-	ROM_LOAD( "e1",   0x16000, 0x1000, CRC(21e4ca9b) SHA1(4024678a4006614051675858ba65db655931a539) )
-	ROM_LOAD( "e3",   0x18000, 0x1000, CRC(a4f735d7) SHA1(110061d1c63a331384729951f93a31e62744d0d7) )
-	ROM_LOAD( "e5",   0x1a000, 0x1000, CRC(0485575b) SHA1(c3be070541459fad4da4a71604883b2f3043374a) )
-	ROM_LOAD( "f5",   0x1c000, 0x1000, CRC(4b11f572) SHA1(4f283c98a7f1bcf534921b4a54cf564335c53e37) )
-	ROM_LOAD( "f7",   0x1e000, 0x1000, CRC(bef67473) SHA1(5759ceeca0bb677cee97b74f1a1087d53c25463a) )
-
-	ROM_REGION( 0x10000, "audiocpu", 0 )
-	ROM_LOAD( "d7",   0xf000, 0x1000, CRC(23b0782e) SHA1(7751327b84235a2e2700e4bdd21adec205c54f0e) )
-
-	ROM_REGION( 0x0300, "proms", 0 )
-	ROM_LOAD( "d1.cpu", 0x000, 0x0100, CRC(8db17a40) SHA1(0e04a4f5f99b302dbbbfda438808d549f8680fe2) )
-	ROM_LOAD( "e1.cpu", 0x100, 0x0100, CRC(3c775c5e) SHA1(ac86f45938c0c9d5fec1245bf86718442baf445b) )
+	ROM_REGION(0xc000, "maincpu", 0)
+	ROM_LOAD("g1", 0x0000, 0x1000, CRC(3467a0ec) SHA1(0b094a9bf772b101acd26cf09009c67dd4785ed2))
+	ROM_LOAD("g3", 0x1000, 0x1000, CRC(9950cdf2) SHA1(b2b59cc1080357de6ba297392881d626157df809))
+	ROM_LOAD("g5", 0x2000, 0x1000, CRC(a4b09879) SHA1(69739dd1d3c88ee6ab310ca3c71b3b50d8ec618f))
+
+	// rom type can be either 2732 or 2764 in all locations
+	ROM_REGION(0xe000, "banked", 0)
+	ROM_LOAD("f1", 0x0000, 0x2000, CRC(ce1b0b8b) SHA1(8ed1d793928bb7afa041a4f61e0c2f78b4442f2f))
+	ROM_LOAD("f3", 0x2000, 0x2000, CRC(6a11072a) SHA1(9700beaec669849da4d0e39d6dbf0b872d7f1b7f))
+	ROM_LOAD("e1", 0x4000, 0x1000, CRC(21e4ca9b) SHA1(4024678a4006614051675858ba65db655931a539))
+	ROM_RELOAD(0x5000, 0x1000)
+	ROM_LOAD("e3", 0x6000, 0x1000, CRC(a4f735d7) SHA1(110061d1c63a331384729951f93a31e62744d0d7))
+	ROM_RELOAD(0x7000, 0x1000)
+	ROM_LOAD("e5", 0x8000, 0x1000, CRC(0485575b) SHA1(c3be070541459fad4da4a71604883b2f3043374a))
+	ROM_RELOAD(0x9000, 0x1000)
+	ROM_LOAD("f5", 0xa000, 0x1000, CRC(4b11f572) SHA1(4f283c98a7f1bcf534921b4a54cf564335c53e37))
+	ROM_RELOAD(0xb000, 0x1000)
+	ROM_LOAD("f7", 0xc000, 0x1000, CRC(bef67473) SHA1(5759ceeca0bb677cee97b74f1a1087d53c25463a))
+	ROM_RELOAD(0xd000, 0x1000)
+
+	ROM_REGION(0x2000, "audiocpu", 0)
+	ROM_LOAD("d7", 0x1000, 0x1000, CRC(23b0782e) SHA1(7751327b84235a2e2700e4bdd21adec205c54f0e))
+
+	ROM_REGION(0x200, "proms", 0)
+	ROM_LOAD("d1.cpu", 0x000, 0x100, CRC(8db17a40) SHA1(0e04a4f5f99b302dbbbfda438808d549f8680fe2))
+	ROM_LOAD("e1.cpu", 0x100, 0x100, CRC(3c775c5e) SHA1(ac86f45938c0c9d5fec1245bf86718442baf445b))
 ROM_END
 
 ROM_START( beezer1 )
-	ROM_REGION( 0x20000, "maincpu", 0 )
-	ROM_LOAD( "g1.32",   0x0d000, 0x1000, CRC(3134cb93) SHA1(7d4a484378b66ccf2fded31885d6dfb2abae9317) )
-	ROM_LOAD( "g3.32",   0x0e000, 0x1000, CRC(a3cb2c2d) SHA1(1e17eb0eaf02f86865845a065a5f714fc51aa7d6) )
-	ROM_LOAD( "g5.32",   0x0f000, 0x1000, CRC(5e559bf9) SHA1(cd3713f3ed1215ea5c5640474ba6f005242cd093) )
-
-	ROM_LOAD( "f1.64",   0x12000, 0x2000, CRC(b8a78cca) SHA1(4218ef8c4c8e10d7cc47d6de4c4d189ef3c0f0a1) )
-	ROM_LOAD( "f3.32",   0x14000, 0x1000, CRC(bfa023f5) SHA1(56fb15e2db61197e1aec5a5825beff7c788a4ba3) )
-	ROM_LOAD( "e1",      0x16000, 0x1000, CRC(21e4ca9b) SHA1(4024678a4006614051675858ba65db655931a539) )
-	ROM_LOAD( "e3",      0x18000, 0x1000, CRC(a4f735d7) SHA1(110061d1c63a331384729951f93a31e62744d0d7) )
-	ROM_LOAD( "e5",      0x1a000, 0x1000, CRC(0485575b) SHA1(c3be070541459fad4da4a71604883b2f3043374a) )
-	ROM_LOAD( "f5",      0x1c000, 0x1000, CRC(4b11f572) SHA1(4f283c98a7f1bcf534921b4a54cf564335c53e37) )
-	ROM_LOAD( "f7",      0x1e000, 0x1000, CRC(bef67473) SHA1(5759ceeca0bb677cee97b74f1a1087d53c25463a) )
-
-	ROM_REGION( 0x10000, "audiocpu", 0 )
-	ROM_LOAD( "d7.32",   0xf000, 0x1000, CRC(b11028b5) SHA1(db8958f0bb12e333ce056da3338f1a824dda36e0) )
-
-	ROM_REGION( 0x0300, "proms", 0 )
-	ROM_LOAD( "d1.cpu", 0x000, 0x0100, CRC(8db17a40) SHA1(0e04a4f5f99b302dbbbfda438808d549f8680fe2) )
-	ROM_LOAD( "e1.cpu", 0x100, 0x0100, CRC(3c775c5e) SHA1(ac86f45938c0c9d5fec1245bf86718442baf445b) )
+	ROM_REGION(0x3000, "maincpu", 0)
+	ROM_LOAD("g1.32", 0x0000, 0x1000, CRC(3134cb93) SHA1(7d4a484378b66ccf2fded31885d6dfb2abae9317))
+	ROM_LOAD("g3.32", 0x1000, 0x1000, CRC(a3cb2c2d) SHA1(1e17eb0eaf02f86865845a065a5f714fc51aa7d6))
+	ROM_LOAD("g5.32", 0x2000, 0x1000, CRC(5e559bf9) SHA1(cd3713f3ed1215ea5c5640474ba6f005242cd093))
+
+	// rom type can be either 2732 or 2764 in all locations
+	ROM_REGION(0xe000, "banked", 0)
+	ROM_LOAD("f1.64", 0x0000, 0x2000, CRC(b8a78cca) SHA1(4218ef8c4c8e10d7cc47d6de4c4d189ef3c0f0a1))
+	ROM_LOAD("f3.32", 0x2000, 0x1000, CRC(bfa023f5) SHA1(56fb15e2db61197e1aec5a5825beff7c788a4ba3))
+	ROM_RELOAD(0x3000, 0x1000)
+	ROM_LOAD("e1",    0x4000, 0x1000, CRC(21e4ca9b) SHA1(4024678a4006614051675858ba65db655931a539))
+	ROM_RELOAD(0x5000, 0x1000)
+	ROM_LOAD("e3",    0x6000, 0x1000, CRC(a4f735d7) SHA1(110061d1c63a331384729951f93a31e62744d0d7))
+	ROM_RELOAD(0x7000, 0x1000)
+	ROM_LOAD("e5",    0x8000, 0x1000, CRC(0485575b) SHA1(c3be070541459fad4da4a71604883b2f3043374a))
+	ROM_RELOAD(0x9000, 0x1000)
+	ROM_LOAD("f5",    0xa000, 0x1000, CRC(4b11f572) SHA1(4f283c98a7f1bcf534921b4a54cf564335c53e37))
+	ROM_RELOAD(0xb000, 0x1000)
+	ROM_LOAD("f7",    0xc000, 0x1000, CRC(bef67473) SHA1(5759ceeca0bb677cee97b74f1a1087d53c25463a))
+	ROM_RELOAD(0xd000, 0x1000)
+
+	ROM_REGION(0x2000, "audiocpu", 0)
+	ROM_LOAD("d7.32", 0x1000, 0x1000, CRC(b11028b5) SHA1(db8958f0bb12e333ce056da3338f1a824dda36e0))
+
+	ROM_REGION(0x200, "proms", 0)
+	ROM_LOAD("d1.cpu", 0x000, 0x100, CRC(8db17a40) SHA1(0e04a4f5f99b302dbbbfda438808d549f8680fe2))
+	ROM_LOAD("e1.cpu", 0x100, 0x100, CRC(3c775c5e) SHA1(ac86f45938c0c9d5fec1245bf86718442baf445b))
 ROM_END
 
-GAME( 1982, beezer,  0,      beezer, beezer, beezer_state, beezer, ROT90, "Tong Electronic", "Beezer (set 1)", MACHINE_IMPERFECT_SOUND )
-GAME( 1982, beezer1, beezer, beezer, beezer, beezer_state, beezer, ROT90, "Tong Electronic", "Beezer (set 2)", MACHINE_IMPERFECT_SOUND )
+
+//**************************************************************************
+//  SYSTEM DRIVERS
+//**************************************************************************
+
+//    YEAR  NAME     PARENT  MACHINE  INPUT   CLASS          INIT  ROTATION  COMPANY            FULLNAME          FLAGS
+GAME( 1982, beezer,  0,      beezer,  beezer, driver_device, 0,    ROT90,    "Tong Electronic", "Beezer (set 1)", MACHINE_IMPERFECT_SOUND )
+GAME( 1982, beezer1, beezer, beezer,  beezer, driver_device, 0,    ROT90,    "Tong Electronic", "Beezer (set 2)", MACHINE_IMPERFECT_SOUND )
diff --git a/src/mame/drivers/bfm_sc2.cpp b/src/mame/drivers/bfm_sc2.cpp
index 03b4069..28fc948 100644
--- a/src/mame/drivers/bfm_sc2.cpp
+++ b/src/mame/drivers/bfm_sc2.cpp
@@ -2523,6 +2523,24 @@ ROM_START( gldncrwn )
 	ROM_LOAD("gcrpal.bin", 0, 8 , CRC(4edd5a1d) SHA1(d6fe38377d5f2291d33ee8ed808548871e63c4d7))
 ROM_END
 
+ROM_START( gldncrwnhop )
+	ROM_REGION( 0x10000, "maincpu", 0 )
+	ROM_LOAD("95752007.gam", 0x00000, 0x10000, CRC(ba009ab7) SHA1(df58f5ff4e9fdf8db5931833b909fb0e4ba8e23d))
+
+	ROM_REGION( 0x20000, "adder2", 0 )
+	ROM_LOAD("95770146.vid", 0x00000, 0x20000, CRC(f3109cd5) SHA1(8da5207c07015d6f5a72397eaa6ab70800785f7f))
+
+	ROM_REGION( 0x20000, "upd", 0 )
+	ROM_LOAD("95770139.snd", 0x00000, 0x20000, CRC(e76ca414) SHA1(2c441e3369e374c033b5585e8f6a9c34a4c5ec0f))
+
+	ROM_REGION( 0x40000, "gfx1", ROMREGION_ERASEFF )
+	ROM_LOAD("95770147.chr", 0x00000, 0x20000, CRC(5a4d2b79) SHA1(c2f2f39ef6816e0da1b2ff4b723612c671c6215f))
+
+	ROM_REGION( 0x10, "proms", 0 )
+	ROM_LOAD("gcrpal.bin", 0, 8 , BAD_DUMP CRC(4edd5a1d) SHA1(d6fe38377d5f2291d33ee8ed808548871e63c4d7)) // This was missing with dump, using gldncrwn
+ROM_END
+
+
 // ROM definition Dutch Paradice //////////////////////////////////////////
 
 ROM_START( paradice )
@@ -7646,6 +7664,7 @@ GAMEL( 1996, sltblgpo, 0,         scorpion2_vid, sltblgpo, bfm_sc2_state,  sltsb
 GAMEL( 1996, sltblgp1, sltblgpo,  scorpion2_vid, sltblgpo, bfm_sc2_state,  sltsbelg,   0,       "BFM/ELAM", "Slots (Belgian Cash, Game Card 95-752-008)",   MACHINE_SUPPORTS_SAVE,layout_sltblgpo )
 
 GAMEL( 1997, gldncrwn, 0,         scorpion2_vid, gldncrwn, bfm_sc2_state,  gldncrwn,   0,       "BFM/ELAM", "Golden Crown (Dutch, Game Card 95-752-011)",   MACHINE_SUPPORTS_SAVE,layout_gldncrwn )
+GAMEL( 1997, gldncrwnhop,gldncrwn,scorpion2_vid, gldncrwn, bfm_sc2_state,  gldncrwn,   0,       "BFM/ELAM", "Golden Crown Hopper (Dutch, Game Card)",   MACHINE_SUPPORTS_SAVE,layout_gldncrwn )
 
 /* Non-Video */
 
diff --git a/src/mame/drivers/bmcbowl.cpp b/src/mame/drivers/bmcbowl.cpp
index ee4c551..74c4e12 100644
--- a/src/mame/drivers/bmcbowl.cpp
+++ b/src/mame/drivers/bmcbowl.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /*
 BMC Bowling (c) 1994.05 BMC, Ltd
diff --git a/src/mame/drivers/bublbobl.cpp b/src/mame/drivers/bublbobl.cpp
index 22581d7..434cc01 100644
--- a/src/mame/drivers/bublbobl.cpp
+++ b/src/mame/drivers/bublbobl.cpp
@@ -192,7 +192,7 @@ MC68705P5 - Motorola MC68705P5 Microcontroller with 2K Internal EPROM,
 
             A71_01.IC1     Sub CPU Program
 
-            A71_24.IC57    68705 Microcontroller Program (Protected, Not Dumped)
+            A71_24.IC57    68705 Microcontroller Program
 
 
 
@@ -389,7 +389,7 @@ static ADDRESS_MAP_START( tokio_map, AS_PROGRAM, 8, bublbobl_state )
 	AM_RANGE(0xfb00, 0xfb00) AM_WRITE(tokio_videoctrl_w)
 	AM_RANGE(0xfb80, 0xfb80) AM_WRITE(bublbobl_nmitrigger_w)
 	AM_RANGE(0xfc00, 0xfc00) AM_READWRITE(bublbobl_sound_status_r, bublbobl_sound_command_w)
-	AM_RANGE(0xfe00, 0xfe00) AM_READ(tokio_mcu_r) AM_WRITENOP // ???
+	AM_RANGE(0xfe00, 0xfe00) AM_READWRITE(tokio_mcu_r, tokio_mcu_w)
 ADDRESS_MAP_END
 
 static ADDRESS_MAP_START( tokio_slave_map, AS_PROGRAM, 8, bublbobl_state )
@@ -669,8 +669,8 @@ static INPUT_PORTS_START( tokio )
 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_SERVICE1 )
 	PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_COIN1 ) PORT_IMPULSE(1)
 	PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_COIN2 ) PORT_IMPULSE(1)
-	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
-	PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_SPECIAL )   // data ready from MCU
+	PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, bublbobl_state,tokio_main_sent_r, nullptr)
+	PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, bublbobl_state,tokio_mcu_sent_r, nullptr)
 	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
 	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
 
@@ -745,16 +745,24 @@ MACHINE_START_MEMBER(bublbobl_state,tokio)
 {
 	MACHINE_START_CALL_MEMBER(common);
 
-	save_item(NAME(m_tokio_prot_count));
+
+	save_item(NAME(m_mcu_sent));
+	save_item(NAME(m_main_sent));
+	save_item(NAME(m_from_main));
+	save_item(NAME(m_from_mcu));
+	save_item(NAME(m_from_mcu_latch));
+	save_item(NAME(m_to_mcu_latch));
+	save_item(NAME(m_old_portB));
 }
 
+
 MACHINE_RESET_MEMBER(bublbobl_state,tokio)
 {
 	MACHINE_RESET_CALL_MEMBER(common);
-
-	m_tokio_prot_count = 0;
 }
 
+
+
 static MACHINE_CONFIG_START( tokio, bublbobl_state )
 
 	/* basic machine hardware */
@@ -769,7 +777,14 @@ static MACHINE_CONFIG_START( tokio, bublbobl_state )
 	MCFG_CPU_ADD("audiocpu", Z80, MAIN_XTAL/8) // 3 MHz
 	MCFG_CPU_PROGRAM_MAP(tokio_sound_map) // NMIs are triggered by the main CPU, IRQs are triggered by the YM2203
 
-	MCFG_QUANTUM_TIME(attotime::from_hz(6000)) // 100 CPU slices per frame - a high value to ensure proper synchronization of the CPUs
+	MCFG_CPU_ADD("mcu", M68705_NEW, MAIN_XTAL/8) // 3 Mhz
+	MCFG_M68705_PORTA_R_CB(READ8(bublbobl_state, tokio_mcu_porta_r))
+	MCFG_M68705_PORTA_W_CB(WRITE8(bublbobl_state, tokio_mcu_porta_w))
+	MCFG_M68705_PORTB_W_CB(WRITE8(bublbobl_state, tokio_mcu_portb_w))
+	MCFG_M68705_PORTC_R_CB(READ8(bublbobl_state, tokio_mcu_portc_r))
+
+
+	MCFG_QUANTUM_PERFECT_CPU("maincpu")
 
 	MCFG_WATCHDOG_ADD("watchdog")
 
@@ -800,6 +815,9 @@ static MACHINE_CONFIG_START( tokio, bublbobl_state )
 	MCFG_SOUND_ROUTE(3, "mono", 1.0)
 MACHINE_CONFIG_END
 
+static MACHINE_CONFIG_DERIVED( tokiob, tokio )
+	MCFG_DEVICE_REMOVE("mcu")
+MACHINE_CONFIG_END
 
 MACHINE_START_MEMBER(bublbobl_state,bublbobl)
 {
@@ -819,6 +837,7 @@ MACHINE_START_MEMBER(bublbobl_state,bublbobl)
 	save_item(NAME(m_port4_out));
 }
 
+
 MACHINE_RESET_MEMBER(bublbobl_state,bublbobl)
 {
 	MACHINE_RESET_CALL_MEMBER(common);
@@ -980,8 +999,8 @@ ROM_START( tokio ) // newer japan set, has -1 revision of roms 02, 03 and 06
 	ROM_REGION( 0x10000, "audiocpu", 0 )    /* audio CPU */
 	ROM_LOAD( "a71-07.ic10",  0x0000, 0x08000, CRC(f298cc7b) SHA1(ebf5c804aa07b7f198ec3e1f8d1e111cd89ebdf3) )
 
-	ROM_REGION( 0x0800, "cpu3", 0 ) /* 2k for the microcontroller (68705P5) */
-	ROM_LOAD( "a71-24.ic57",  0x0000, 0x0800, NO_DUMP )
+	ROM_REGION( 0x0800, "mcu", 0 ) /* 2k for the microcontroller (68705P5) */
+	ROM_LOAD( "a71__24.ic57",  0x0000, 0x0800, CRC(0f4b25de) SHA1(e2d82aa8d8cc6a86aaf5715ef9cb62f526fd5b11) )
 
 	ROM_REGION( 0x80000, "gfx1", ROMREGION_INVERT ) /* gfx roms, on gfx board */
 	ROM_LOAD( "a71-08.ic12",  0x00000, 0x8000, CRC(0439ab13) SHA1(84142220a6a29f0e34f7c7c751b583bf394df8ce) )    /* 1st plane */
@@ -1023,8 +1042,8 @@ ROM_START( tokioo ) // older japan set, has older roms 02, 03, 06
 	ROM_REGION( 0x10000, "audiocpu", 0 )    /* audio CPU */
 	ROM_LOAD( "a71-07.ic10",  0x0000, 0x08000, CRC(f298cc7b) SHA1(ebf5c804aa07b7f198ec3e1f8d1e111cd89ebdf3) )
 
-	ROM_REGION( 0x0800, "cpu3", 0 ) /* 2k for the microcontroller (68705P5) */
-	ROM_LOAD( "a71-24.ic57",  0x0000, 0x0800, NO_DUMP )
+	ROM_REGION( 0x0800, "mcu", 0 ) /* 2k for the microcontroller (68705P5) */
+	ROM_LOAD( "a71__24.ic57",  0x0000, 0x0800, CRC(0f4b25de) SHA1(e2d82aa8d8cc6a86aaf5715ef9cb62f526fd5b11) )
 
 	ROM_REGION( 0x80000, "gfx1", ROMREGION_INVERT ) /* gfx roms, on gfx board */
 	ROM_LOAD( "a71-08.ic12",  0x00000, 0x8000, CRC(0439ab13) SHA1(84142220a6a29f0e34f7c7c751b583bf394df8ce) )    /* 1st plane */
@@ -1066,8 +1085,8 @@ ROM_START( tokiou )
 	ROM_REGION( 0x10000, "audiocpu", 0 )    /* audio CPU */
 	ROM_LOAD( "a71-07.ic10",  0x0000, 0x08000, CRC(f298cc7b) SHA1(ebf5c804aa07b7f198ec3e1f8d1e111cd89ebdf3) )
 
-	ROM_REGION( 0x0800, "cpu3", 0 ) /* 2k for the microcontroller (68705P5) */
-	ROM_LOAD( "a71-24.ic57",  0x0000, 0x0800, NO_DUMP )
+	ROM_REGION( 0x0800, "mcu", 0 ) /* 2k for the microcontroller (68705P5) */
+	ROM_LOAD( "a71__24.ic57",  0x0000, 0x0800, CRC(0f4b25de) SHA1(e2d82aa8d8cc6a86aaf5715ef9cb62f526fd5b11) )
 
 	ROM_REGION( 0x80000, "gfx1", ROMREGION_INVERT ) /* gfx roms, on gfx board */
 	ROM_LOAD( "a71-08.ic12",  0x00000, 0x8000, CRC(0439ab13) SHA1(84142220a6a29f0e34f7c7c751b583bf394df8ce) )    /* 1st plane */
@@ -1880,10 +1899,10 @@ DRIVER_INIT_MEMBER(bublbobl_state,dland)
  *
  *************************************/
 
-GAME( 1986, tokio,      0,        tokio,    tokio,      bublbobl_state, tokio,    ROT90, "Taito Corporation", "Tokio / Scramble Formation (newer)", MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION | MACHINE_SUPPORTS_SAVE )
-GAME( 1986, tokioo,     tokio,    tokio,    tokio,      bublbobl_state, tokio,    ROT90, "Taito Corporation", "Tokio / Scramble Formation (older)", MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION | MACHINE_SUPPORTS_SAVE )
-GAME( 1986, tokiou,     tokio,    tokio,    tokio,      bublbobl_state, tokio,    ROT90, "Taito America Corporation (Romstar license)", "Tokio / Scramble Formation (US)", MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION | MACHINE_SUPPORTS_SAVE )
-GAME( 1986, tokiob,     tokio,    tokio,    tokio,      bublbobl_state, tokiob,   ROT90, "bootleg", "Tokio / Scramble Formation (bootleg)", MACHINE_SUPPORTS_SAVE )
+GAME( 1986, tokio,      0,        tokio,    tokio,      bublbobl_state, tokio,    ROT90, "Taito Corporation", "Tokio / Scramble Formation (newer)", MACHINE_SUPPORTS_SAVE )
+GAME( 1986, tokioo,     tokio,    tokio,    tokio,      bublbobl_state, tokio,    ROT90, "Taito Corporation", "Tokio / Scramble Formation (older)", MACHINE_SUPPORTS_SAVE )
+GAME( 1986, tokiou,     tokio,    tokio,    tokio,      bublbobl_state, tokio,    ROT90, "Taito America Corporation (Romstar license)", "Tokio / Scramble Formation (US)", MACHINE_SUPPORTS_SAVE )
+GAME( 1986, tokiob,     tokio,    tokiob,   tokio,      bublbobl_state, tokiob,   ROT90, "bootleg", "Tokio / Scramble Formation (bootleg)", MACHINE_SUPPORTS_SAVE )
 
 GAME( 1986, bublbobl,   0,        bublbobl, bublbobl,   bublbobl_state, bublbobl, ROT0,  "Taito Corporation", "Bubble Bobble (Japan, Ver 0.1)", MACHINE_SUPPORTS_SAVE )
 GAME( 1986, bublbobl1,  bublbobl, bublbobl, bublbobl,   bublbobl_state, bublbobl, ROT0,  "Taito Corporation", "Bubble Bobble (Japan, Ver 0.0)", MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/drivers/by35.cpp b/src/mame/drivers/by35.cpp
index 604de9a..b5fbb39 100644
--- a/src/mame/drivers/by35.cpp
+++ b/src/mame/drivers/by35.cpp
@@ -2306,7 +2306,7 @@ ROM_START(uboat65)
 	ROM_RELOAD(0x28000, 0x8000)
 	ROM_RELOAD(0x38000, 0x8000)
 	ROM_REGION(0x10000, "cpu2", 0)
-	ROM_COPY("sound1", 0x0000, 0x8000,0x8000)
+	ROM_LOAD("snd_u8.bin", 0x8000, 0x8000, CRC(d00fd4fd) SHA1(23f6b7c5d60821eb7fa2fdcfc85caeb536eef99a))
 ROM_END
 /*--------------------------------
 / Big Ball Bowling (Bowler)
diff --git a/src/mame/drivers/cardline.cpp b/src/mame/drivers/cardline.cpp
index ccd295e..705a73b 100644
--- a/src/mame/drivers/cardline.cpp
+++ b/src/mame/drivers/cardline.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 
 /************************************
diff --git a/src/mame/drivers/ccastles.cpp b/src/mame/drivers/ccastles.cpp
index 170e738..ef9c310 100644
--- a/src/mame/drivers/ccastles.cpp
+++ b/src/mame/drivers/ccastles.cpp
@@ -361,8 +361,10 @@ static INPUT_PORTS_START( ccastles )
 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_TILT )
 	PORT_SERVICE( 0x10, IP_ACTIVE_LOW )
 	PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, ccastles_state,get_vblank, nullptr)
-	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON1 )                    /* 1p Jump, non-cocktail start1 */
-	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)     /* 2p Jump, non-cocktail start2 */
+	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("Left Jump/1P Start Upright")    PORT_CONDITION("IN1",0x20,EQUALS,0x00)  /* left Jump, non-cocktail start1 */
+	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("1P Jump")           PORT_CONDITION("IN1",0x20,EQUALS,0x20)  /* 1p Jump, cocktail */
+	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("Right Jump/2P Start Upright")   PORT_CONDITION("IN1",0x20,EQUALS,0x00)  /* right Jump, non-cocktail start2 */
+	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_COCKTAIL PORT_NAME("2P Jump") PORT_CONDITION("IN1",0x20,EQUALS,0x20)  /* 2p Jump, cocktail */
 
 	PORT_START("IN1")   /* IN1 */
 	PORT_DIPNAME( 0x01, 0x01, DEF_STR( Unknown ) )
@@ -374,8 +376,8 @@ static INPUT_PORTS_START( ccastles )
 	PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) )
 	PORT_DIPSETTING(    0x04, DEF_STR( Off ) )
 	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
-	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START1 )             /* cocktail only */
-	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START2 )             /* cocktail only */
+	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START1 ) PORT_NAME("1P Start Cocktail")  /* cocktail only */
+	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START2 ) PORT_NAME("2P Start Cocktail")  /* cocktail only */
 	PORT_DIPNAME( 0x20, 0x00, DEF_STR( Cabinet ) )
 	PORT_DIPSETTING(    0x00, DEF_STR( Upright ) )
 	PORT_DIPSETTING(    0x20, DEF_STR( Cocktail ) )
@@ -388,10 +390,10 @@ static INPUT_PORTS_START( ccastles )
 	PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_X ) PORT_SENSITIVITY(10) PORT_KEYDELTA(30)
 
 	PORT_START("LETA2")
-	PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_Y ) PORT_COCKTAIL PORT_SENSITIVITY(10) PORT_KEYDELTA(30) PORT_REVERSE
+	PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_Y ) PORT_COCKTAIL PORT_SENSITIVITY(10) PORT_KEYDELTA(30) PORT_REVERSE   /* cocktail only */
 
 	PORT_START("LETA3")
-	PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_X ) PORT_COCKTAIL PORT_SENSITIVITY(10) PORT_KEYDELTA(30)
+	PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_X ) PORT_COCKTAIL PORT_SENSITIVITY(10) PORT_KEYDELTA(30)            /* cocktail only */
 INPUT_PORTS_END
 
 
diff --git a/src/mame/drivers/cchance.cpp b/src/mame/drivers/cchance.cpp
index dddb53b..199631d 100644
--- a/src/mame/drivers/cchance.cpp
+++ b/src/mame/drivers/cchance.cpp
@@ -39,19 +39,20 @@ cha3    $10d8
 #include "includes/tnzs.h"
 #include "sound/ay8910.h"
 
-class cchance_state : public tnzs_state
+class cchance_state : public tnzs_base_state
 {
 public:
 	cchance_state(const machine_config &mconfig, device_type type, const char *tag)
-		: tnzs_state(mconfig, type, tag) { }
+		: tnzs_base_state(mconfig, type, tag) { }
+
+	void machine_reset() override;
+	void machine_start() override;
 
 	uint8_t m_hop_io;
 	uint8_t m_bell_io;
 	DECLARE_WRITE8_MEMBER(output_0_w);
 	DECLARE_READ8_MEMBER(input_1_r);
 	DECLARE_WRITE8_MEMBER(output_1_w);
-	DECLARE_MACHINE_START(cchance);
-	DECLARE_MACHINE_RESET(cchance);
 };
 
 
@@ -191,18 +192,17 @@ static GFXDECODE_START( cchance )
 	GFXDECODE_ENTRY( "gfx1", 0, cchance_layout,   0x0, 32  )
 GFXDECODE_END
 
-MACHINE_START_MEMBER(cchance_state,cchance)
+void cchance_state::machine_start()
 {
 	save_item(NAME(m_hop_io));
 	save_item(NAME(m_bell_io));
 }
 
-MACHINE_RESET_MEMBER(cchance_state,cchance)
+void cchance_state::machine_reset()
 {
-	m_mcu_type = -1;
+	tnzs_base_state::machine_reset();
 	m_hop_io = 0;
 	m_bell_io = 0;
-
 }
 
 static MACHINE_CONFIG_START( cchance, cchance_state )
@@ -211,9 +211,6 @@ static MACHINE_CONFIG_START( cchance, cchance_state )
 	MCFG_CPU_PROGRAM_MAP(main_map)
 	MCFG_CPU_VBLANK_INT_DRIVER("screen", cchance_state,  irq0_line_hold)
 
-	MCFG_MACHINE_START_OVERRIDE(cchance_state,cchance)
-	MCFG_MACHINE_RESET_OVERRIDE(cchance_state,cchance)
-
 	MCFG_GFXDECODE_ADD("gfxdecode", "palette", cchance)
 
 	MCFG_DEVICE_ADD("spritegen", SETA001_SPRITE, 0)
@@ -230,7 +227,7 @@ static MACHINE_CONFIG_START( cchance, cchance_state )
 	MCFG_SCREEN_PALETTE("palette")
 
 	MCFG_PALETTE_ADD("palette", 512)
-	MCFG_PALETTE_INIT_OWNER(cchance_state,arknoid2)
+	MCFG_PALETTE_INIT_OWNER(tnzs_base_state, prompalette)
 
 	MCFG_SPEAKER_STANDARD_MONO("mono")
 
diff --git a/src/mame/drivers/cchasm.cpp b/src/mame/drivers/cchasm.cpp
index c5375bb..c4124e0 100644
--- a/src/mame/drivers/cchasm.cpp
+++ b/src/mame/drivers/cchasm.cpp
@@ -189,8 +189,7 @@ static MACHINE_CONFIG_START( cchasm, cchasm_state )
 	MCFG_SOUND_ROUTE_EX(0, "dac2", 1.0, DAC_VREF_POS_INPUT)
 
 	/* 6840 PTM */
-	MCFG_DEVICE_ADD("6840ptm", PTM6840, 0)
-	MCFG_PTM6840_INTERNAL_CLOCK(CCHASM_68K_CLOCK/10)
+	MCFG_DEVICE_ADD("6840ptm", PTM6840, CCHASM_68K_CLOCK/10)
 	MCFG_PTM6840_EXTERNAL_CLOCKS(0, CCHASM_68K_CLOCK / 10, 0)
 	MCFG_PTM6840_IRQ_CB(INPUTLINE("maincpu", 4))
 MACHINE_CONFIG_END
diff --git a/src/mame/drivers/cedar_magnet.cpp b/src/mame/drivers/cedar_magnet.cpp
index 8f667be..1b97260 100644
--- a/src/mame/drivers/cedar_magnet.cpp
+++ b/src/mame/drivers/cedar_magnet.cpp
@@ -15,8 +15,6 @@
   - verify the disk images, convert to a better format that can natively store protection
     * RAW data also available if required
     * as mentioned, the disks are copy protected, see notes below
-    * are the bad tiles shortly into the first level of mag_exzi caused by a bad dump or
-      bad comms?
   - Use proper floppy drive emulation code that originally came from MESS (tied with above)
   - verify all clocks and screen params (50hz seems to match original videos)
   - work out why we need a protection hack and replace it with proper emulation
@@ -845,8 +843,8 @@ ROM_END
 ROM_START( mag_exzi )
 	BIOS_ROM
 
-	ROM_REGION( 0x100000, "flop:disk", ROMREGION_ERASE00 ) // I don't 100% trust this one
-	ROM_LOAD( "exzisus.img", 0x00000, 0xf0000, BAD_DUMP CRC(1ac7409e) SHA1(b894bd65b0b9699e18a1ab49f309c460488f0ef8) )
+	ROM_REGION( 0x100000, "flop:disk", ROMREGION_ERASE00 )
+	ROM_LOAD( "exzisus.img", 0x00000, 0xf0000, CRC(3705e9dc) SHA1(78c8010d224f5deb202a29bd273ea7dc85ddcdb4) )
 ROM_END
 
 ROM_START( mag_xain )
@@ -909,8 +907,8 @@ DRIVER_INIT_MEMBER(cedar_magnet_state, mag_exzi)
 	m_prothack = mag_exzi_protection_hack;
 }
 
-GAME( 1987, cedmag,    0,         cedar_magnet, cedar_magnet, driver_device,       0,        ROT0,  "EFO SA / Cedar", "Magnet System (prototype)", MACHINE_IS_BIOS_ROOT )
+GAME( 1987, cedmag,    0,         cedar_magnet, cedar_magnet, driver_device,       0,        ROT0,  "EFO SA / Cedar", "Magnet System", MACHINE_IS_BIOS_ROOT )
 
-GAME( 1987, mag_time,  cedmag,    cedar_magnet, cedar_magnet, cedar_magnet_state,  mag_time, ROT90, "EFO SA / Cedar", "Time Scanner (TS 2.0, Magnet System, prototype)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) // original game was by Sega
-GAME( 1987, mag_exzi,  cedmag,    cedar_magnet, cedar_magnet, cedar_magnet_state,  mag_exzi, ROT0,  "EFO SA / Cedar", "Exzisus (EX 1.0, Magnet System, prototype)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) // original game was by Taito
-GAME( 1987, mag_xain,  cedmag,    cedar_magnet, cedar_magnet, cedar_magnet_state,  mag_xain, ROT0,  "EFO SA / Cedar", "Xain'd Sleena (SC 3.0, Magnet System, prototype)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) // original game was by Technos
+GAME( 1987, mag_time,  cedmag,    cedar_magnet, cedar_magnet, cedar_magnet_state,  mag_time, ROT90, "EFO SA / Cedar", "Time Scanner (TS 2.0, Magnet System)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) // original game was by Sega
+GAME( 1987, mag_exzi,  cedmag,    cedar_magnet, cedar_magnet, cedar_magnet_state,  mag_exzi, ROT0,  "EFO SA / Cedar", "Exzisus (EX 1.0, Magnet System)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) // original game was by Taito
+GAME( 1987, mag_xain,  cedmag,    cedar_magnet, cedar_magnet, cedar_magnet_state,  mag_xain, ROT0,  "EFO SA / Cedar", "Xain'd Sleena (SC 3.0, Magnet System)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) // original game was by Technos
diff --git a/src/mame/drivers/chanbara.cpp b/src/mame/drivers/chanbara.cpp
index f4ff955..7303bd0 100644
--- a/src/mame/drivers/chanbara.cpp
+++ b/src/mame/drivers/chanbara.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina, David Haywood
 /****************************************************************************************
 Chanbara
diff --git a/src/mame/drivers/chihiro.cpp b/src/mame/drivers/chihiro.cpp
index cb025df..02b2842 100644
--- a/src/mame/drivers/chihiro.cpp
+++ b/src/mame/drivers/chihiro.cpp
@@ -56,13 +56,13 @@ Games on this system include....
 | | 2005     | Sega Network Taisen Mahjong MJ 3 (Rev E)           | Sega                     | GDROM  | GDX-0017E  | 317-0414-JPN |
 |*| 2005     | Sega Network Taisen Mahjong MJ 3 (Rev F)           | Sega                     | GDROM  | GDX-0017F  | 317-0414-JPN |
 | | 2005     | Sega Club Golf 2006: Next Tours                    | Sega                     | GDROM  | GDX-0018   |              |
-|*| 2005     | Sega Club Golf 2006: Next Tours (Rev A)            | Sega                     | GDROM  | GDX-0018A  |              |
+|*| 2005     | Sega Club Golf 2006: Next Tours (Rev A)            | Sega                     | GDROM  | GDX-0018A  | ?            |
 | | 2006     | Sega Network Taisen Mahjong MJ 3 Evolution         | Sega                     | GDROM  | GDX-0021   |              |
 | | 2006     | Sega Network Taisen Mahjong MJ 3 Evolution (Rev A) | Sega                     | GDROM  | GDX-0021A  |              |
-|*| 2007     | Sega Network Taisen Mahjong MJ 3 Evolution (Rev B) | Sega                     | GDROM  | GDX-0021B  |              |
+|*| 2007     | Sega Network Taisen Mahjong MJ 3 Evolution (Rev B) | Sega                     | GDROM  | GDX-0021B  | ?            |
 | | 2009     | Firmware Update For Compact Flash Box              | Sega                     | GDROM  | GDX-0024   |              |
 |*| 2009     | Firmware Update For Compact Flash Box (Rev A)      | Sega                     | GDROM  | GDX-0024A  | 317-0567-EXP |
-|*| 2004     | Quest Of D Ver.1.01C                               | Sega                     | CDROM  | CDV-10005C |              |
+|*| 2004     | Quest Of D Ver.1.01C                               | Sega                     | CDROM  | CDV-10005C | 317-0376-JPN |
 |*| 2005     | Sangokushi Taisen Ver.1.002                        | Sega                     | DVDROM | CDV-10009D |              |
 |*| 2005     | Mobile Suit Gundam 0079 Card Builder               | Banpresto                | DVDROM | CDV-10010  | 317-0415-JPN |
 |*| 2006     | Sangokushi Taisen 2 Ver.2.007                      | Sega                     | DVDROM | CDV-10019A |              |
@@ -385,7 +385,7 @@ Thanks to Alex, Mr Mudkips, and Philip Burke for this info.
 #include "debug/debugcon.h"
 #include "debug/debugcmd.h"
 #include "debugger.h"
-#include "includes/chihiro.h"
+#include "includes/xbox_nv2a.h"
 #include "includes/xbox.h"
 #include "includes/xbox_usb.h"
 #include "machine/jvshost.h"
@@ -562,7 +562,6 @@ public:
 private:
 	void jamtable_disasm(address_space &space, uint32_t address, uint32_t size);
 	void jamtable_disasm_command(int ref, int params, const char **param);
-	void threadlist_command(int ref, int params, const char **param);
 	void chihiro_help_command(int ref, int params, const char **param);
 	void debug_commands(int ref, int params, const char **param);
 };
@@ -694,43 +693,12 @@ void chihiro_state::jamtable_disasm_command(int ref, int params, const char **pa
 	jamtable_disasm(space, (uint32_t)addr, (uint32_t)size);
 }
 
-void chihiro_state::threadlist_command(int ref, int params, const char **param)
-{
-	const uint32_t thlists = 0x8003aae0; // magic address
-	address_space &space = m_maincpu->space();
-	debugger_cpu &cpu = machine().debugger().cpu();
-	debugger_console &con = machine().debugger().console();
-
-	con.printf("Pri. _KTHREAD   Stack  Function\n");
-	con.printf("-------------------------------\n");
-	for (int pri=0;pri < 16;pri++)
-	{
-		uint32_t curr = thlists + pri * 8;
-		uint32_t next = cpu.read_dword(space, curr, true);
-
-		while (next != curr)
-		{
-			uint32_t kthrd = next - 0x5c;
-			uint32_t topstack = cpu.read_dword(space, kthrd + 0x1c, true);
-			uint32_t tlsdata = cpu.read_dword(space, kthrd + 0x28, true);
-			uint32_t function;
-			if (tlsdata == 0)
-				function = cpu.read_dword(space, topstack - 0x210 - 8, true);
-			else
-				function = cpu.read_dword(space, tlsdata - 8, true);
-			con.printf(" %02d  %08x %08x %08x\n", pri, kthrd, topstack, function);
-			next = cpu.read_dword(space, next, true);
-		}
-	}
-}
-
 void chihiro_state::chihiro_help_command(int ref, int params, const char **param)
 {
 	debugger_console &con = machine().debugger().console();
 
 	con.printf("Available Chihiro commands:\n");
 	con.printf("  chihiro jamdis,<start>,<size> -- Disassemble <size> bytes of JamTable instructions starting at <start>\n");
-	con.printf("  chihiro threadlist -- list of currently active threads\n");
 	con.printf("  chihiro help -- this list\n");
 }
 
@@ -740,8 +708,6 @@ void chihiro_state::debug_commands(int ref, int params, const char **param)
 		return;
 	if (strcmp("jamdis", param[0]) == 0)
 		jamtable_disasm_command(ref, params - 1, param + 1);
-	else if (strcmp("threadlist", param[0]) == 0)
-		threadlist_command(ref, params - 1, param + 1);
 	else
 		chihiro_help_command(ref, params - 1, param + 1);
 }
@@ -756,7 +722,8 @@ void chihiro_state::hack_eeprom()
 }
 
 #define HACK_ITEMS 5
-static const struct {
+static const struct
+{
 	const char *game_name;
 	const bool disable_usb;
 	struct {
@@ -2060,8 +2027,8 @@ ROM_START( questofd )
 	DISK_IMAGE_READONLY( "cdv-10005c", 0, SHA1(b30238cf8697fb7313fedbe75b70641e9418090f) )
 
 	ROM_REGION( 0x4000, "pic", ROMREGION_ERASEFF)
-	//PIC16C621A brute-forced key, label is unknown
-	ROM_LOAD("317-xxxx-xxx.pic", 0x00, 0x4000, CRC(c6914d97) SHA1(e86897efcca86f303117d1ead6ede53ac410add8) )
+	//PIC16C621A (317-0376-JPN)
+	ROM_LOAD("317-0376-jpn.pic", 0x00, 0x4000, CRC(c6914d97) SHA1(e86897efcca86f303117d1ead6ede53ac410add8) )
 ROM_END
 
 ROM_START( gundcb79 )
diff --git a/src/mame/drivers/clcd.cpp b/src/mame/drivers/clcd.cpp
index 391bb56..063cc6b 100644
--- a/src/mame/drivers/clcd.cpp
+++ b/src/mame/drivers/clcd.cpp
@@ -134,32 +134,25 @@ public:
 			uint8_t *font = m_lcd_char_rom->base();
 			if (m_lcd_mode & LCD_MODE_ALT)
 			{
-				font += 1024;
+				font += 2048;
 			}
 
 			int chrw = (m_lcd_size & LCD_SIZE_CHRW) ? 8 : 6;
 
-			for (int y = 0; y < 16; y++)
+			for (int y = 0; y < 128; y++)
 			{
-				int offset = (m_lcd_scrolly * 128) + (m_lcd_scrollx & 0x7f) + (y * 128);
+				int offset = (m_lcd_scrolly * 128) + (m_lcd_scrollx & 0x7f) + ((y / 8) * 128);
 
 				for (int x = 0; x < 480; x++)
 				{
 					uint8_t ch = m_ram->pointer()[offset + (x / chrw)];
-					uint8_t bit = font[((ch & 0x7f) * chrw) + (x % chrw)];
+					uint8_t bit = font[((ch & 0x7f) * 8) + (y % 8)];
 					if (ch & 0x80)
 					{
 						bit = ~bit;
 					}
 
-					bitmap.pix16((y * 8) + 0, x) = (bit >> 0) & 1;
-					bitmap.pix16((y * 8) + 1, x) = (bit >> 1) & 1;
-					bitmap.pix16((y * 8) + 2, x) = (bit >> 2) & 1;
-					bitmap.pix16((y * 8) + 3, x) = (bit >> 3) & 1;
-					bitmap.pix16((y * 8) + 4, x) = (bit >> 4) & 1;
-					bitmap.pix16((y * 8) + 5, x) = (bit >> 5) & 1;
-					bitmap.pix16((y * 8) + 6, x) = (bit >> 6) & 1;
-					bitmap.pix16((y * 8) + 7, x) = (bit >> 7) & 1;
+					bitmap.pix16(y, x) = (bit >> (7 - (x % chrw))) & 1;
 				}
 			}
 		}
@@ -838,8 +831,8 @@ ROM_START( clcd )
 	ROM_LOAD( "sizapr.u103",        0x10000, 0x8000, CRC(0aa91d9f) SHA1(f0842f370607f95d0a0ec6afafb81bc063c32745))
 	ROM_LOAD( "kizapr.u102",        0x18000, 0x8000, CRC(59103d52) SHA1(e49c20b237a78b54c2cb26b133d5903bb60bd8ef))
 
-	ROM_REGION( 0x20000, "lcd_char_rom", 0 )
-	ROM_LOAD( "lcd_char_rom",      0x000000, 0x000800, BAD_DUMP CRC(7db9d225) SHA1(0a8835fa182efa55d027828b42aa554608795274) )
+	ROM_REGION( 0x1000, "lcd_char_rom", 0 )
+	ROM_LOAD( "lcd-char-rom.u16",   0x00000, 0x1000, CRC(7b6d3867) SHA1(cb594801438849f933ddc3e64b03b56f42f59f09))
 ROM_END
 
 
diff --git a/src/mame/drivers/cmi.cpp b/src/mame/drivers/cmi.cpp
index b9456f7..7de7e74 100644
--- a/src/mame/drivers/cmi.cpp
+++ b/src/mame/drivers/cmi.cpp
@@ -323,8 +323,7 @@ MACHINE_CONFIG_FRAGMENT( cmi01a_device )
 	MCFG_PIA_IRQA_HANDLER(WRITELINE(cmi01a_device, pia_1_irqa))
 	MCFG_PIA_IRQB_HANDLER(WRITELINE(cmi01a_device, pia_1_irqb))
 
-	MCFG_DEVICE_ADD("cmi01a_ptm", PTM6840, 0) // ptm_cmi01a_config
-	MCFG_PTM6840_INTERNAL_CLOCK(2000000)
+	MCFG_DEVICE_ADD("cmi01a_ptm", PTM6840, 2000000) // ptm_cmi01a_config
 	MCFG_PTM6840_EXTERNAL_CLOCKS(250000, 500000, 500000)
 	MCFG_PTM6840_OUT0_CB(WRITELINE(cmi01a_device, ptm_out0))
 	MCFG_PTM6840_IRQ_CB(WRITELINE(cmi01a_device, ptm_irq))
@@ -2793,8 +2792,7 @@ static MACHINE_CONFIG_START( cmi2x, cmi_state )
 	MCFG_PIA_WRITEPB_HANDLER(WRITE8(cmi_state, q133_1_portb_w));
 
 	MCFG_DEVICE_ADD("q133_pia_2", PIA6821, 0) // pia_q133_2_config
-	MCFG_DEVICE_ADD("q133_ptm", PTM6840, 0) // ptm_q133_config
-	MCFG_PTM6840_INTERNAL_CLOCK(2000000)
+	MCFG_DEVICE_ADD("q133_ptm", PTM6840, 2000000) // ptm_q133_config
 	MCFG_PTM6840_EXTERNAL_CLOCKS(1024, 1, 111) // Third is todo
 
 	MCFG_DEVICE_ADD("q219_pia", PIA6821, 0) // pia_q219_config
@@ -2804,8 +2802,7 @@ static MACHINE_CONFIG_START( cmi2x, cmi_state )
 	MCFG_PIA_IRQA_HANDLER(WRITELINE(cmi_state, pia_q219_irqa))
 	MCFG_PIA_IRQB_HANDLER(WRITELINE(cmi_state, pia_q219_irqb))
 
-	MCFG_DEVICE_ADD("q219_ptm", PTM6840, 0) // ptm_q219_config
-	MCFG_PTM6840_INTERNAL_CLOCK(2000000)
+	MCFG_DEVICE_ADD("q219_ptm", PTM6840, 2000000) // ptm_q219_config
 	MCFG_PTM6840_EXTERNAL_CLOCKS(HBLANK_FREQ, VBLANK_FREQ, 1000000)
 	MCFG_PTM6840_IRQ_CB(WRITELINE(cmi_state, ptm_q219_irq))
 
@@ -2814,8 +2811,7 @@ static MACHINE_CONFIG_START( cmi2x, cmi_state )
 
 	MCFG_DEVICE_ADD("cmi02_pia_2", PIA6821, 0) // pia_cmi02_2_config
 
-	MCFG_DEVICE_ADD("cmi02_ptm", PTM6840, 0) // ptm_cmi02_config
-	MCFG_PTM6840_INTERNAL_CLOCK(2000000) // TODO
+	MCFG_DEVICE_ADD("cmi02_ptm", PTM6840, 2000000) // ptm_cmi02_config TODO
 	MCFG_PTM6840_OUT1_CB(WRITELINE(cmi_state, cmi02_ptm_o1))
 	MCFG_PTM6840_IRQ_CB(WRITELINE(cmi_state, cmi02_ptm_irq))
 
@@ -2870,8 +2866,7 @@ static MACHINE_CONFIG_START( cmi2x, cmi_state )
 	MCFG_DEVICE_ADD("ank_pia_clock", CLOCK, 9600)
 	MCFG_CLOCK_SIGNAL_HANDLER(DEVWRITELINE("ank_pia", pia6821_device, ca1_w))
 
-	MCFG_DEVICE_ADD("cmi07_ptm", PTM6840, 0) // ptm_cmi07_config
-	MCFG_PTM6840_INTERNAL_CLOCK(2000000) // TODO
+	MCFG_DEVICE_ADD("cmi07_ptm", PTM6840, 2000000) // ptm_cmi07_config TODO
 	MCFG_PTM6840_IRQ_CB(WRITELINE(cmi_state, cmi07_irq))
 
 	MCFG_FD1791_ADD("wd1791", XTAL_16MHz / 8) // wd1791_interface
diff --git a/src/mame/drivers/coco12.cpp b/src/mame/drivers/coco12.cpp
index aa9ec93..5c3239b 100644
--- a/src/mame/drivers/coco12.cpp
+++ b/src/mame/drivers/coco12.cpp
@@ -24,6 +24,7 @@
 ***************************************************************************/
 
 #include "includes/coco12.h"
+#include "bus/coco/coco_t4426.h"
 #include "bus/coco/coco_232.h"
 #include "bus/coco/coco_orch90.h"
 #include "bus/coco/coco_pak.h"
@@ -264,7 +265,13 @@ SLOT_INTERFACE_START( coco_cart )
 	SLOT_INTERFACE("multi", COCO_MULTIPAK)
 SLOT_INTERFACE_END
 
+//-------------------------------------------------
+//  SLOT_INTERFACE_START(t4426_cart)
+//-------------------------------------------------
 
+SLOT_INTERFACE_START( t4426_cart )
+	SLOT_INTERFACE("t4426", COCO_T4426)
+SLOT_INTERFACE_END
 
 //-------------------------------------------------
 //  MACHINE_CONFIG_FRAGMENT( coco_sound )
@@ -392,6 +399,14 @@ static MACHINE_CONFIG_DERIVED( cp400, coco )
 	MCFG_COCO_CARTRIDGE_HALT_CB(INPUTLINE(MAINCPU_TAG, INPUT_LINE_HALT))
 MACHINE_CONFIG_END
 
+static MACHINE_CONFIG_DERIVED( t4426, coco2 )
+	MCFG_COCO_CARTRIDGE_REMOVE(CARTRIDGE_TAG)
+	MCFG_COCO_CARTRIDGE_ADD(CARTRIDGE_TAG, t4426_cart, "t4426")
+	MCFG_COCO_CARTRIDGE_CART_CB(WRITELINE(coco_state, cart_w))
+	MCFG_COCO_CARTRIDGE_NMI_CB(INPUTLINE(MAINCPU_TAG, INPUT_LINE_NMI))
+	MCFG_COCO_CARTRIDGE_HALT_CB(INPUTLINE(MAINCPU_TAG, INPUT_LINE_HALT))
+	MCFG_SLOT_FIXED(true) // This cart is fixed so no way to change it
+MACHINE_CONFIG_END
 
 //**************************************************************************
 //  ROMS
@@ -431,6 +446,12 @@ ROM_START(mx1600 )
 	ROM_LOAD("mx1600extbas.rom", 0x0000, 0x2000, CRC(322a3d58) SHA1(9079a477c3f22e46cebb1e68b61df5bd607c71a4))
 ROM_END
 
+ROM_START( t4426 )
+	ROM_REGION(0x8000,MAINCPU_TAG,0)
+	ROM_LOAD("SOFT4426-U13-1.2.bin", 0x2000, 0x2000, CRC(3c1af94a) SHA1(1dc57b3e4a6ef6a743ca21d8f111a74b1ea9d54e))
+	ROM_LOAD("SOFT4426-U14-1.2.bin", 0x0000, 0x2000, CRC(e031d076) SHA1(7275f1e3f165ff6a4657e4e5e24cb8b817239f54))
+ROM_END
+
 ROM_START(lzcolor64 )
 	ROM_REGION(0x8000,MAINCPU_TAG,0)
 	ROM_LOAD("color64bas.rom",    0x2000, 0x2000, CRC(b0717d71) SHA1(ad1beef9d6f095ada69f91d0b8ad75985172d86f))
@@ -444,8 +465,9 @@ ROM_END
 /*     YEAR     NAME        PARENT  COMPAT  MACHINE    INPUT      INIT    COMPANY                 FULLNAME */
 COMP(  1980,    coco,       0,      0,      coco,      coco, driver_device,      0,      "Tandy Radio Shack",    "Color Computer", 0)
 COMP(  1981,    cocoe,      coco,   0,      cocoe,     coco, driver_device,      0,      "Tandy Radio Shack",    "Color Computer (Extended BASIC 1.0)", 0)
-COMP(  1983,    coco2,      coco,   0,      coco2,     coco, driver_device,      0,      "Tandy Radio Shack",     "Color Computer 2", 0)
-COMP(  1985?,   coco2b,     coco,   0,      coco2b,    coco, driver_device,      0,      "Tandy Radio Shack",     "Color Computer 2B", 0)
+COMP(  1983,    coco2,      coco,   0,      coco2,     coco, driver_device,      0,      "Tandy Radio Shack",    "Color Computer 2", 0)
+COMP(  1985?,   coco2b,     coco,   0,      coco2b,    coco, driver_device,      0,      "Tandy Radio Shack",    "Color Computer 2B", 0)
 COMP(  1984,    cp400,      coco,   0,      cp400,     coco, driver_device,      0,      "Prologica",            "CP400", 0)
 COMP(  1984,    lzcolor64,  coco,   0,      coco,      coco, driver_device,      0,      "Digiponto",            "LZ Color64", 0)
 COMP(  1984,    mx1600,     coco,   0,      coco,      coco, driver_device,      0,      "Dynacom",              "MX-1600", 0)
+COMP(  1986,    t4426,      coco,   0,      t4426,     coco, driver_device,      0,      "Terco AB",             "Terco 4426 CNC Programming station", MACHINE_NOT_WORKING)
diff --git a/src/mame/drivers/cps1.cpp b/src/mame/drivers/cps1.cpp
index ca475e8..d863be1 100644
--- a/src/mame/drivers/cps1.cpp
+++ b/src/mame/drivers/cps1.cpp
@@ -4026,7 +4026,7 @@ ROM_START( daimakai )
 	ROM_LOAD( "sou1",         0x0000, 0x0117, CRC(84f4b2fe) SHA1(dcc9e86cc36316fe42eace02d6df75d08bc8bb6d) )
 
 	ROM_REGION( 0x0200, "bboardplds", 0 )
-	ROM_LOAD( "dm22a.1a",     0x0000, 0x0117, NO_DUMP )
+	ROM_LOAD( "dm22a.1a",     0x0000, 0x0117, CRC(d4776116) SHA1(802d8bc18ad2b8c998e5338a0aa4e74895de2c81) )
 	ROM_LOAD( "lwio.12c",     0x0000, 0x0117, CRC(ad52b90c) SHA1(f0fd6aeea515ee449320fe15684e6b3ab7f97bf4) )
 ROM_END
 
diff --git a/src/mame/drivers/ct486.cpp b/src/mame/drivers/ct486.cpp
index 1af48cb..781f1de 100644
--- a/src/mame/drivers/ct486.cpp
+++ b/src/mame/drivers/ct486.cpp
@@ -174,7 +174,6 @@ static MACHINE_CONFIG_START( ct486, ct486_state )
 
 	/* software lists */
 	MCFG_SOFTWARE_LIST_ADD("pc_disk_list","ibm5150")
-	MCFG_SOFTWARE_LIST_ADD("xt_disk_list","ibm5160_flop")
 	MCFG_SOFTWARE_LIST_ADD("at_disk_list","ibm5170")
 	MCFG_SOFTWARE_LIST_ADD("at_cdrom_list","ibm5170_cdrom")
 MACHINE_CONFIG_END
diff --git a/src/mame/drivers/d9final.cpp b/src/mame/drivers/d9final.cpp
index 9fc6d97..9d1328e 100644
--- a/src/mame/drivers/d9final.cpp
+++ b/src/mame/drivers/d9final.cpp
@@ -288,6 +288,7 @@ GFXDECODE_END
 void d9final_state::machine_start()
 {
 	membank("bank1")->configure_entries(0, 8, memregion("maincpu")->base() + 0x10000, 0x4000);
+	membank("bank1")->set_entry(0);
 }
 
 static MACHINE_CONFIG_START( d9final, d9final_state )
diff --git a/src/mame/drivers/darkmist.cpp b/src/mame/drivers/darkmist.cpp
index 62a1b7c..b08e235 100644
--- a/src/mame/drivers/darkmist.cpp
+++ b/src/mame/drivers/darkmist.cpp
@@ -13,6 +13,10 @@ driver by
 Main CPU : z80 (with encryption, external to z80)
 Sound CPU: custom T5182 cpu (like seibu sound system but with internal code)
 
+The SEI8608B sound board, which features the T5182 "CPU CUSTOM" and YM2151, also
+has unpopulated locations for a 76489AN, 2x MSM5205, 2x 27512 EPROM (presumably
+for ADPCM samples), and additional TTL chips to support all these.
+
 $e000 - coins (two bytes)
 $e2b7 - player 1 energy
 
diff --git a/src/mame/drivers/ddealer.cpp b/src/mame/drivers/ddealer.cpp
index dec791a..6ecf09b 100644
--- a/src/mame/drivers/ddealer.cpp
+++ b/src/mame/drivers/ddealer.cpp
@@ -9,7 +9,7 @@
     Appears to be a down-grade of the nmk16 HW
 
     TODO:
-    -When you use the "gun card" the game gives "minus" points,but points are always added,inaccurate protection?
+    -When you use the "gun card" the game gives "minus" points, but points are always added, inaccurate protection?
     -Understand better the video emulation and convert it to tilemaps;
     -Coinage settings based on those listed at www.crazykong.com/dips/DoubleDealer.txt - coin/credit simulation need fixing;
     -Decap + emulate MCU, required if the random number generation is going to be accurate;
@@ -51,10 +51,10 @@
 
     - There's also MCU response (write/read/test) test just after these writes.
       (probably data used in the check depends on above writes). It's similar to
-      jalmah.c tests, but num of responses is different, and  shared ram is
+      jalmah.cpp tests, but num of responses is different, and  shared ram is
       used to communicate with MCU
 
-    - After last check (or maybe durning tests ... no idea)
+    - After last check (or maybe during tests ... no idea)
       MCU writes $4ef900000604 (jmp $604) to $fe000 and game jumps to this address.
 
     - code at $604  writes $20.w to $fe018 and $1.w to $fe01e.
@@ -144,38 +144,40 @@ public:
 	required_shared_ptr<uint16_t> m_work_ram;
 	required_shared_ptr<uint16_t> m_mcu_shared_ram;
 
+	/* devices */
+	required_device<cpu_device> m_maincpu;
+	required_device<gfxdecode_device> m_gfxdecode;
+	required_device<palette_device> m_palette;
+
 	/* video-related */
 	tilemap_t  *m_back_tilemap;
 	int      m_respcount;
-	int      m_flipscreen;
 
 	/* misc */
 	uint8_t    m_input_pressed;
 	uint16_t   m_coin_input;
-	DECLARE_WRITE16_MEMBER(ddealer_flipscreen_w);
+
+	DECLARE_WRITE16_MEMBER(flipscreen_w);
 	DECLARE_WRITE16_MEMBER(back_vram_w);
-	DECLARE_WRITE16_MEMBER(ddealer_vregs_w);
-	DECLARE_WRITE16_MEMBER(ddealer_mcu_shared_w);
-	DECLARE_READ16_MEMBER(ddealer_mcu_r);
+	DECLARE_WRITE16_MEMBER(mcu_shared_w);
+	DECLARE_READ16_MEMBER(mcu_r);
+
 	DECLARE_DRIVER_INIT(ddealer);
 	TILE_GET_INFO_MEMBER(get_back_tile_info);
 	virtual void machine_start() override;
 	virtual void machine_reset() override;
 	virtual void video_start() override;
-	uint32_t screen_update_ddealer(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
-	INTERRUPT_GEN_MEMBER(ddealer_interrupt);
-	TIMER_DEVICE_CALLBACK_MEMBER(ddealer_mcu_sim);
-	required_device<cpu_device> m_maincpu;
-	required_device<gfxdecode_device> m_gfxdecode;
-	required_device<palette_device> m_palette;
-	void ddealer_draw_video_layer( uint16_t* vreg_base, uint16_t* top, uint16_t* bottom, bitmap_ind16 &bitmap, const rectangle &cliprect, int flipy);
+	uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
+	INTERRUPT_GEN_MEMBER(interrupt);
+	TIMER_DEVICE_CALLBACK_MEMBER(mcu_sim);
+	void draw_video_layer(uint16_t* vreg_base, uint16_t* top, uint16_t* bottom, bitmap_ind16 &bitmap, const rectangle &cliprect, int flipy);
 };
 
 
 
-WRITE16_MEMBER(ddealer_state::ddealer_flipscreen_w)
+WRITE16_MEMBER(ddealer_state::flipscreen_w)
 {
-	m_flipscreen = data & 0x01;
+	flip_screen_set(data & 0x01);
 }
 
 TILE_GET_INFO_MEMBER(ddealer_state::get_back_tile_info)
@@ -189,11 +191,10 @@ TILE_GET_INFO_MEMBER(ddealer_state::get_back_tile_info)
 
 void ddealer_state::video_start()
 {
-	m_flipscreen = 0;
 	m_back_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(ddealer_state::get_back_tile_info),this), TILEMAP_SCAN_COLS, 8, 8, 64, 32);
 }
 
-void ddealer_state::ddealer_draw_video_layer( uint16_t* vreg_base, uint16_t* top, uint16_t* bottom, bitmap_ind16 &bitmap, const rectangle &cliprect, int flipy)
+void ddealer_state::draw_video_layer(uint16_t* vreg_base, uint16_t* top, uint16_t* bottom, bitmap_ind16 &bitmap, const rectangle &cliprect, int flipy)
 {
 	gfx_element *gfx = m_gfxdecode->gfx(1);
 
@@ -276,40 +277,40 @@ void ddealer_state::ddealer_draw_video_layer( uint16_t* vreg_base, uint16_t* top
 }
 
 
-uint32_t ddealer_state::screen_update_ddealer(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
+uint32_t ddealer_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
 {
-	m_back_tilemap->set_scrollx(0, m_flipscreen ? -192 : -64);
-	m_back_tilemap->set_flip(m_flipscreen ? TILEMAP_FLIPY | TILEMAP_FLIPX : 0);
+	m_back_tilemap->set_scrollx(0, -64);
 	m_back_tilemap->draw(screen, bitmap, cliprect, 0, 0);
 
 	/* the fg tilemap handling is a little hacky right now,
-	   i'm not sure if it should be a single tilemap with
+	   I'm not sure if it should be a single tilemap with
 	   rowscroll / linescroll, or two tilemaps which can be
 	   combined, the flipscreen case makes things more
 	   difficult to understand */
+	bool const flip = flip_screen();
 
-	if (!m_flipscreen)
+	if (!flip)
 	{
 		if (m_vregs[0xcc / 2] & 0x80)
 		{
-			ddealer_draw_video_layer(&m_vregs[0x1e0 / 2], m_left_fg_vram_top, m_left_fg_vram_bottom, bitmap, cliprect, m_flipscreen);
-			ddealer_draw_video_layer(&m_vregs[0xcc / 2], m_right_fg_vram_top, m_right_fg_vram_bottom, bitmap, cliprect, m_flipscreen);
+			draw_video_layer(&m_vregs[0x1e0 / 2], m_left_fg_vram_top, m_left_fg_vram_bottom, bitmap, cliprect, flip);
+			draw_video_layer(&m_vregs[0xcc / 2], m_right_fg_vram_top, m_right_fg_vram_bottom, bitmap, cliprect, flip);
 		}
 		else
 		{
-			ddealer_draw_video_layer(&m_vregs[0x1e0 / 2], m_left_fg_vram_top, m_left_fg_vram_bottom, bitmap, cliprect, m_flipscreen);
+			draw_video_layer(&m_vregs[0x1e0 / 2], m_left_fg_vram_top, m_left_fg_vram_bottom, bitmap, cliprect, flip);
 		}
 	}
 	else
 	{
 		if (m_vregs[0xcc / 2] & 0x80)
 		{
-			ddealer_draw_video_layer(&m_vregs[0xcc / 2], m_left_fg_vram_top, m_left_fg_vram_bottom, bitmap, cliprect, m_flipscreen);
-			ddealer_draw_video_layer(&m_vregs[0x1e0 / 2], m_right_fg_vram_top, m_right_fg_vram_bottom, bitmap, cliprect, m_flipscreen);
+			draw_video_layer(&m_vregs[0xcc / 2], m_left_fg_vram_top, m_left_fg_vram_bottom, bitmap, cliprect, flip);
+			draw_video_layer(&m_vregs[0x1e0 / 2], m_right_fg_vram_top, m_right_fg_vram_bottom, bitmap, cliprect, flip);
 		}
 		else
 		{
-			ddealer_draw_video_layer(&m_vregs[0x1e0 / 2], m_left_fg_vram_top, m_left_fg_vram_bottom, bitmap, cliprect, m_flipscreen);
+			draw_video_layer(&m_vregs[0x1e0 / 2], m_left_fg_vram_top, m_left_fg_vram_bottom, bitmap, cliprect, flip);
 		}
 
 	}
@@ -317,7 +318,7 @@ uint32_t ddealer_state::screen_update_ddealer(screen_device &screen, bitmap_ind1
 	return 0;
 }
 
-TIMER_DEVICE_CALLBACK_MEMBER(ddealer_state::ddealer_mcu_sim)
+TIMER_DEVICE_CALLBACK_MEMBER(ddealer_state::mcu_sim)
 {
 	/*coin/credit simulation*/
 	/*$fe002 is used,might be for multiple coins for one credit settings.*/
@@ -351,7 +352,7 @@ TIMER_DEVICE_CALLBACK_MEMBER(ddealer_state::ddealer_mcu_sim)
 		m_input_pressed = (m_input_pressed & 0xfb);
 
 	/*0x104/2 is some sort of "start-lock",i.e. used on the girl selection.
-	  Without it,the game "steals" one credit if you press the start button on that.*/
+	  Without it, the game "steals" one credit if you press the start button on that.*/
 	if (m_mcu_shared_ram[0x000 / 2] > 0 && m_work_ram[0x104 / 2] & 1)
 	{
 		if (m_coin_input & 0x08)//start 1
@@ -373,7 +374,7 @@ TIMER_DEVICE_CALLBACK_MEMBER(ddealer_state::ddealer_mcu_sim)
 			m_input_pressed = (m_input_pressed & 0xef);
 	}
 
-	/*random number generators,controls order of cards*/
+	/*random number generators, controls order of cards*/
 	m_mcu_shared_ram[0x10 / 2] = machine().rand() & 0xffff;
 	m_mcu_shared_ram[0x12 / 2] = machine().rand() & 0xffff;
 	m_mcu_shared_ram[0x14 / 2] = machine().rand() & 0xffff;
@@ -389,14 +390,9 @@ WRITE16_MEMBER(ddealer_state::back_vram_w)
 }
 
 
-WRITE16_MEMBER(ddealer_state::ddealer_vregs_w)
-{
-	COMBINE_DATA(&m_vregs[offset]);
-}
-
 /******************************************************************************************************
 
-Protection handling,identical to Hacha Mecha Fighter / Thunder Dragon with different vectors.
+Protection handling, identical to Hacha Mecha Fighter / Thunder Dragon with different vectors.
 
 ******************************************************************************************************/
 
@@ -415,7 +411,7 @@ Protection handling,identical to Hacha Mecha Fighter / Thunder Dragon with diffe
 		m_mcu_shared_ram[_protinput_+1] = (_input_ & 0x0000ffff);\
 	}
 
-WRITE16_MEMBER(ddealer_state::ddealer_mcu_shared_w)
+WRITE16_MEMBER(ddealer_state::mcu_shared_w)
 {
 	COMBINE_DATA(&m_mcu_shared_ram[offset]);
 
@@ -425,7 +421,7 @@ WRITE16_MEMBER(ddealer_state::ddealer_mcu_shared_w)
 		case 0x164/2: PROT_INPUT(0x164/2,0x5678,0x104/2,0x80002); break;
 		case 0x62e/2: PROT_INPUT(0x62e/2,0x9ca3,0x108/2,0x80008); break;
 		case 0x734/2: PROT_INPUT(0x734/2,0xaba2,0x10c/2,0x8000a); break;
-/*These enables something for sure,maybe the random number generator?*/
+/*These enables something for sure, maybe the random number generator?*/
 	//00054C: 33FC B891 000F E828        move.w  #$b891, $fe828.l
 	//000554: 33FC C760 000F E950        move.w  #$c760, $fe950.l
 	//00055C: 33FC D45F 000F EA7C        move.w  #$d45f, $fea7c.l
@@ -447,7 +443,7 @@ WRITE16_MEMBER(ddealer_state::ddealer_mcu_shared_w)
 		case 0x4de/2: PROT_JSR(0x4de,0x803b,0x96c2); break;
 		case 0x4ee/2: PROT_JSR(0x4ee,0x800c,0x5ca4); break;//palette ram buffer
 		case 0x4fe/2: PROT_JSR(0x4fe,0x8018,0x9818); break;
-		/*Start-up vector,I think that only the first ram address can be written by the main CPU,or it is a whole sequence.*/
+		/*Start-up vector, I think that only the first ram address can be written by the main CPU, or it is a whole sequence.*/
 		case 0x000/2:
 			if (m_mcu_shared_ram[0x000 / 2] == 0x60fe)
 			{
@@ -480,7 +476,7 @@ static ADDRESS_MAP_START( ddealer, AS_PROGRAM, 16, ddealer_state )
 	AM_RANGE(0x08000a, 0x08000b) AM_READ_PORT("UNK")
 	AM_RANGE(0x084000, 0x084003) AM_DEVWRITE8("ymsnd", ym2203_device, write, 0x00ff) // ym ?
 	AM_RANGE(0x088000, 0x0887ff) AM_RAM_DEVWRITE("palette", palette_device, write) AM_SHARE("palette")
-	AM_RANGE(0x08c000, 0x08cfff) AM_RAM_WRITE(ddealer_vregs_w) AM_SHARE("vregs") // palette ram
+	AM_RANGE(0x08c000, 0x08cfff) AM_RAM AM_SHARE("vregs") // palette ram
 
 	/* this might actually be 1 tilemap with some funky rowscroll / columnscroll enabled, I'm not sure */
 	AM_RANGE(0x090000, 0x090fff) AM_RAM AM_SHARE("left_fg_vratop")
@@ -488,10 +484,10 @@ static ADDRESS_MAP_START( ddealer, AS_PROGRAM, 16, ddealer_state )
 	AM_RANGE(0x092000, 0x092fff) AM_RAM AM_SHARE("left_fg_vrabot")
 	AM_RANGE(0x093000, 0x093fff) AM_RAM AM_SHARE("right_fg_vrabot")
 	//AM_RANGE(0x094000, 0x094001) AM_NOP // always 0?
-	AM_RANGE(0x098000, 0x098001) AM_WRITE(ddealer_flipscreen_w)
+	AM_RANGE(0x098000, 0x098001) AM_WRITE(flipscreen_w)
 	AM_RANGE(0x09c000, 0x09cfff) AM_RAM_WRITE(back_vram_w) AM_SHARE("back_vram") // bg tilemap
 	AM_RANGE(0x0f0000, 0x0fdfff) AM_RAM AM_SHARE("work_ram")
-	AM_RANGE(0x0fe000, 0x0fefff) AM_RAM_WRITE(ddealer_mcu_shared_w) AM_SHARE("mcu_shared_ram")
+	AM_RANGE(0x0fe000, 0x0fefff) AM_RAM_WRITE(mcu_shared_w) AM_SHARE("mcu_shared_ram")
 	AM_RANGE(0x0ff000, 0x0fffff) AM_RAM
 ADDRESS_MAP_END
 
@@ -502,7 +498,7 @@ static INPUT_PORTS_START( ddealer )
 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SERVICE1 )
 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START1 )
 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START2 )
-	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN ) //used,"test" in service mode,unknown purpose
+	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN ) //used, "test" in service mode, unknown purpose
 	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
 	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
 
@@ -601,7 +597,6 @@ GFXDECODE_END
 void ddealer_state::machine_start()
 {
 	save_item(NAME(m_respcount));
-	save_item(NAME(m_flipscreen));
 	save_item(NAME(m_input_pressed));
 	save_item(NAME(m_coin_input));
 }
@@ -609,12 +604,11 @@ void ddealer_state::machine_start()
 void ddealer_state::machine_reset()
 {
 	m_respcount = 0;
-	m_flipscreen = 0;
 	m_input_pressed = 0;
 	m_coin_input = 0;
 }
 
-INTERRUPT_GEN_MEMBER(ddealer_state::ddealer_interrupt)
+INTERRUPT_GEN_MEMBER(ddealer_state::interrupt)
 {
 	device.execute().set_input_line(4, HOLD_LINE);
 }
@@ -623,8 +617,8 @@ static MACHINE_CONFIG_START( ddealer, ddealer_state )
 
 	MCFG_CPU_ADD("maincpu" , M68000, XTAL_16MHz/2) /* 8MHz */
 	MCFG_CPU_PROGRAM_MAP(ddealer)
-	MCFG_CPU_VBLANK_INT_DRIVER("screen", ddealer_state,  ddealer_interrupt)
-	MCFG_CPU_PERIODIC_INT_DRIVER(ddealer_state, irq1_line_hold,  90)//guess,controls music tempo,112 is way too fast
+	MCFG_CPU_VBLANK_INT_DRIVER("screen", ddealer_state,  interrupt)
+	MCFG_CPU_PERIODIC_INT_DRIVER(ddealer_state, irq1_line_hold,  90)//guess, controls music tempo, 112 is way too fast
 
 	// M50747 or NMK-110 8131 MCU
 
@@ -636,13 +630,13 @@ static MACHINE_CONFIG_START( ddealer, ddealer_state )
 	MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
 	MCFG_SCREEN_SIZE(512, 256)
 	MCFG_SCREEN_VISIBLE_AREA(0*8, 48*8-1, 2*8, 30*8-1)
-	MCFG_SCREEN_UPDATE_DRIVER(ddealer_state, screen_update_ddealer)
+	MCFG_SCREEN_UPDATE_DRIVER(ddealer_state, screen_update)
 	MCFG_SCREEN_PALETTE("palette")
 
 	MCFG_PALETTE_ADD("palette", 0x400)
 	MCFG_PALETTE_FORMAT(RRRRGGGGBBBBRGBx)
 
-	MCFG_TIMER_DRIVER_ADD_PERIODIC("coinsim", ddealer_state, ddealer_mcu_sim, attotime::from_hz(10000))
+	MCFG_TIMER_DRIVER_ADD_PERIODIC("coinsim", ddealer_state, mcu_sim, attotime::from_hz(10000))
 
 	MCFG_SPEAKER_STANDARD_MONO("mono")
 	MCFG_SOUND_ADD("ymsnd", YM2203, XTAL_6MHz / 8) /* 7.5KHz */
@@ -651,7 +645,7 @@ MACHINE_CONFIG_END
 
 
 
-READ16_MEMBER(ddealer_state::ddealer_mcu_r)
+READ16_MEMBER(ddealer_state::mcu_r)
 {
 	static const int resp[] =
 	{
@@ -674,7 +668,7 @@ READ16_MEMBER(ddealer_state::ddealer_mcu_r)
 
 DRIVER_INIT_MEMBER(ddealer_state,ddealer)
 {
-	m_maincpu->space(AS_PROGRAM).install_read_handler(0xfe01c, 0xfe01d, read16_delegate(FUNC(ddealer_state::ddealer_mcu_r), this));
+	m_maincpu->space(AS_PROGRAM).install_read_handler(0xfe01c, 0xfe01d, read16_delegate(FUNC(ddealer_state::mcu_r), this));
 }
 
 ROM_START( ddealer )
diff --git a/src/mame/drivers/de_2.cpp b/src/mame/drivers/de_2.cpp
index 7e2daaa..628e465 100644
--- a/src/mame/drivers/de_2.cpp
+++ b/src/mame/drivers/de_2.cpp
@@ -630,6 +630,17 @@ MACHINE_CONFIG_END
 /*--------------------------------------------------------------------------------
 / Back To the Future - CPU Rev 3 /Alpha Type 3 - 32K Roms - 32/64K Sound Roms
 /--------------------------------------------------------------------------------*/
+ROM_START(bttf_a28)
+	ROM_REGION(0x10000, "maincpu", 0)
+	ROM_LOAD("bttfb5.2-8", 0x4000, 0x4000, CRC(a7dafa3c) SHA1(a29b8986d1886aa7bb7dea2521c3d7143ab75320))
+	ROM_LOAD("bttfc5.2-8", 0x8000, 0x8000, CRC(5dc9928f) SHA1(03de05ed7b04ba86d695f03b1a3d65788faf2d4f))
+	ROM_REGION(0x10000, "audiocpu", 0)
+	ROM_LOAD("bttfsf7.rom", 0x8000, 0x8000, CRC(7673146e) SHA1(d6bd7cf39c78c8aff0b1a0b6cfd46a2a8ce9e086))
+	ROM_REGION(0x1000000, "sound1", 0)
+	ROM_LOAD("bttfsf6.rom", 0x00000, 0x10000, CRC(468a8d9c) SHA1(713cf84cc5f0531e2e9f7aaa58ebeb53c28ba395))
+	ROM_LOAD("bttfsf5.rom", 0x10000, 0x10000, CRC(37a6f6b8) SHA1(ebd603d36527a2af25dcda1fde5cdf9a34d1f9cd))
+ROM_END
+
 ROM_START(bttf_a27)
 	ROM_REGION(0x10000, "maincpu", 0)
 	ROM_LOAD("bttfb5.2-7", 0x4000, 0x4000, CRC(24b53174) SHA1(00a5e47e70ce4244873980c946479f0bbc414f2e))
@@ -725,6 +736,17 @@ ROM_END
 /*-----------------------------------------------------------------------------------
 / Monday Night Football - CPU Rev 2 /Alpha Type 3 16/32K Roms - 32/64K Sound Roms
 /----------------------------------------------------------------------------------*/
+ROM_START(mnfb_c29)
+	ROM_REGION(0x10000, "maincpu", 0)
+	ROM_LOAD("mnfb2-9.b5", 0x4000, 0x4000, BAD_DUMP CRC(2d6805d1) SHA1(f222cbf30d07975279eea210738f7d4f73b3fcf4)) // patched by PINMAME dev
+	ROM_LOAD("mnfb2-9.c5", 0x8000, 0x8000, CRC(98d50cf5) SHA1(59d3b16f8195ab95cece71a12dab3349dfeb2c2b))
+	ROM_REGION(0x10000, "audiocpu", 0)
+	ROM_LOAD("mnf-f7.256", 0x8000, 0x8000, CRC(fbc2d6f6) SHA1(33173c081de776d32e926481e94b265ec48d770b))
+	ROM_REGION(0x40000, "sound1", 0)
+	ROM_LOAD("mnf-f5-6.512", 0x00000, 0x10000, CRC(0c6ea963) SHA1(8c88fa588222ef8a6c872b8c5b49639b108384d4))
+	ROM_LOAD("mnf-f4-5.512", 0x10000, 0x10000, CRC(efca5d80) SHA1(9655c885dd64aa170205170b6a0c052bd9367379))
+ROM_END
+
 ROM_START(mnfb_c27)
 	ROM_REGION(0x10000, "maincpu", 0)
 	ROM_LOAD("mnfb2-7.b5", 0x4000, 0x4000, CRC(995eb9b8) SHA1(d05d74393fda59ffd8d7b5546313779cdb10d23e))
@@ -924,15 +946,17 @@ ROM_START(torp_a16)
 ROM_END
 
 
-GAME(1990,  bttf_a27,       0,          de_type3,   de_2, de_2_state,   de_2,   ROT0,   "Data East",    "Back To the Future (2.7)",                                     MACHINE_IS_SKELETON_MECHANICAL)
-GAME(1990,  bttf_a20,       bttf_a27,   de_type3,   de_2, de_2_state,   de_2,   ROT0,   "Data East",    "Back To the Future (2.0)",                                     MACHINE_IS_SKELETON_MECHANICAL)
-GAME(1990,  bttf_a21,       bttf_a27,   de_type3,   de_2, de_2_state,   de_2,   ROT0,   "Data East",    "Back To The Future (2.1)",                                     MACHINE_IS_SKELETON_MECHANICAL)
-GAME(199?,  bttf_g27,       bttf_a27,   de_type3,   de_2, de_2_state,   de_2,   ROT0,   "Data East",    "Back To the Future (2.7 Germany)",                             MACHINE_IS_SKELETON_MECHANICAL)
+GAME(1990,  bttf_a28,       0,          de_type3,   de_2, de_2_state,   de_2,   ROT0,   "Data East",    "Back To the Future (2.8)",                                     MACHINE_IS_SKELETON_MECHANICAL)
+GAME(1990,  bttf_a27,       bttf_a28,   de_type3,   de_2, de_2_state,   de_2,   ROT0,   "Data East",    "Back To the Future (2.7)",                                     MACHINE_IS_SKELETON_MECHANICAL)
+GAME(1990,  bttf_a20,       bttf_a28,   de_type3,   de_2, de_2_state,   de_2,   ROT0,   "Data East",    "Back To the Future (2.0)",                                     MACHINE_IS_SKELETON_MECHANICAL)
+GAME(1990,  bttf_a21,       bttf_a28,   de_type3,   de_2, de_2_state,   de_2,   ROT0,   "Data East",    "Back To The Future (2.1)",                                     MACHINE_IS_SKELETON_MECHANICAL)
+GAME(199?,  bttf_g27,       bttf_a28,   de_type3,   de_2, de_2_state,   de_2,   ROT0,   "Data East",    "Back To the Future (2.7 Germany)",                             MACHINE_IS_SKELETON_MECHANICAL)
 GAME(1990,  kiko_a10,       0,          de_type3,   de_2, de_2_state,   de_2,   ROT0,   "Data East",        "King Kong (1.0)",           MACHINE_IS_SKELETON_MECHANICAL)
 GAME(1987,  lwar_a83,       0,          de_type1,   de_2, de_2_state,   de_2,   ROT0,   "Data East",        "Laser War (8.3)",           MACHINE_IS_SKELETON_MECHANICAL)
 GAME(1987,  lwar_a81,       lwar_a83,   de_type1,   de_2, de_2_state,   de_2,   ROT0,   "Data East",        "Laser War (8.1)",           MACHINE_IS_SKELETON_MECHANICAL)
 GAME(1987,  lwar_e90,       lwar_a83,   de_type1,   de_2, de_2_state,   de_2,   ROT0,   "Data East",        "Laser War (9.0 Europe)",    MACHINE_IS_SKELETON_MECHANICAL)
-GAME(1989,  mnfb_c27,       0,          de_type2_alpha3,   de_2, de_2_state,   de_2,   ROT0,   "Data East",        "Monday Night Football (2.7, 50cts)",       MACHINE_IS_SKELETON_MECHANICAL)
+GAME(1989,  mnfb_c29,       0,          de_type2_alpha3,   de_2, de_2_state,   de_2,   ROT0,   "Data East",        "Monday Night Football (2.9, 50cts)",       MACHINE_IS_SKELETON_MECHANICAL)
+GAME(1989,  mnfb_c27,       mnfb_c29,   de_type2_alpha3,   de_2, de_2_state,   de_2,   ROT0,   "Data East",        "Monday Night Football (2.7, 50cts)",       MACHINE_IS_SKELETON_MECHANICAL)
 GAME(1990,  poto_a32,       0,          de_type2_alpha3,   de_2, de_2_state,   de_2,   ROT0,   "Data East",        "The Phantom of the Opera (3.2)",           MACHINE_IS_SKELETON_MECHANICAL)
 GAME(1990,  poto_a29,       poto_a32,   de_type2_alpha3,   de_2, de_2_state,   de_2,   ROT0,   "Data East",        "The Phantom of the Opera (2.9)",           MACHINE_IS_SKELETON_MECHANICAL)
 GAME(1989,  play_a24,       0,          de_type2,   de_2, de_2_state,   de_2,   ROT0,   "Data East",        "Playboy 35th Anniversary (2.4)",           MACHINE_IS_SKELETON_MECHANICAL)
diff --git a/src/mame/drivers/dec0.cpp b/src/mame/drivers/dec0.cpp
index fabe82a..d350869 100644
--- a/src/mame/drivers/dec0.cpp
+++ b/src/mame/drivers/dec0.cpp
@@ -43,7 +43,9 @@ Original Service Manuals and Service Mode (when available).
 
 ToDo:
 - Fix protection simulation in Birdie Try (that part needs at least comparison with a real board);
-- graphics are completely broken in Automat and Secret Agent (bootleg);
+- Fix remaining graphical problems in Automat (bootleg);
+- Fix remaining sound problems in Secret Agent (bootleg);
+- graphics are completely broken in Secret Agent (bootleg);
 - Fighting Fantasy (bootleg) doesn't boot at all;
 - Hook up the 68705 in Midnight Resistance (bootleg) (it might not be used, leftover from the Fighting Fantasy bootleg on the same PCB?)
 - Get rid of ROM patches in Sly Spy and Hippodrome;
@@ -280,6 +282,15 @@ WRITE16_MEMBER(dec0_state::midres_sound_w)
 	}
 }
 
+WRITE16_MEMBER(dec0_automat_state::secretab_sound_w)
+{
+	if (ACCESSING_BITS_0_7)
+	{
+		m_soundlatch->write(space, 0, data & 0xff);
+		m_audiocpu->set_input_line(0, HOLD_LINE);
+	}
+}
+
 /******************************************************************************/
 
 static ADDRESS_MAP_START( dec0_map, AS_PROGRAM, 16, dec0_state )
@@ -531,9 +542,14 @@ ADDRESS_MAP_END
 
 void dec0_automat_state::machine_start()
 {
-	save_item(NAME(m_automat_adpcm_byte));
-	save_item(NAME(m_automat_msm5205_vclk_toggle));
+	m_adpcm_toggle1 = false;
+	m_adpcm_toggle2 = false;
+	save_item(NAME(m_adpcm_toggle1));
+	save_item(NAME(m_adpcm_toggle2));
 	save_item(NAME(m_automat_scroll_regs));
+
+	m_soundbank->configure_entries(0, 8, memregion("audiocpu")->base(), 0x4000);
+	m_soundbank->set_entry(0);
 }
 
 
@@ -584,6 +600,8 @@ static ADDRESS_MAP_START( automat_map, AS_PROGRAM, 16, dec0_automat_state )
 	AM_RANGE(0x400000, 0x400007) AM_WRITE(automat_scroll_w)
 	AM_RANGE(0x400008, 0x400009) AM_WRITE(dec0_priority_w)
 
+	AM_RANGE(0x500000, 0x500001) AM_WRITENOP // ???
+
 	AM_RANGE(0xff8000, 0xffbfff) AM_RAM AM_SHARE("ram")             /* Main ram */
 	AM_RANGE(0xffc000, 0xffcfff) AM_RAM AM_SHARE("spriteram")           /* Sprites */
 ADDRESS_MAP_END
@@ -603,7 +621,7 @@ static ADDRESS_MAP_START( secretab_map, AS_PROGRAM, 16, dec0_automat_state )
 //  AM_RANGE(0x340400, 0x3407ff) AM_DEVREADWRITE("tilegen1", deco_bac06_device, pf_rowscroll_r, pf_rowscroll_w)
 
 	AM_RANGE(0x314008, 0x31400f) AM_READ(slyspy_controls_r)
-//  AM_RANGE(0x314000, 0x314003) AM_WRITE(slyspy_control_w)
+	AM_RANGE(0x314000, 0x314001) AM_WRITE(secretab_sound_w)
 
 	AM_RANGE(0x300000, 0x300007) AM_RAM
 	AM_RANGE(0x300010, 0x300017) AM_RAM
@@ -616,19 +634,28 @@ static ADDRESS_MAP_START( secretab_map, AS_PROGRAM, 16, dec0_automat_state )
 ADDRESS_MAP_END
 
 
-WRITE8_MEMBER(dec0_automat_state::automat_adpcm_w)
-{
-	m_automat_adpcm_byte = data;
-}
-
 static ADDRESS_MAP_START( automat_s_map, AS_PROGRAM, 8, dec0_automat_state )
-	AM_RANGE(0x0103, 0x0103) AM_WRITENOP
+	AM_RANGE(0x0000, 0x7fff) AM_ROM
+	AM_RANGE(0x8000, 0xbfff) AM_ROMBANK("soundbank")
 	AM_RANGE(0xc000, 0xc7ff) AM_RAM
-	AM_RANGE(0xc800, 0xc801) AM_DEVWRITE("2203a", ym2203_device, write)
-	AM_RANGE(0xd800, 0xd800) AM_DEVREAD("soundlatch", generic_latch_8_device, read)
-	AM_RANGE(0xd000, 0xd001) AM_DEVWRITE("2203b", ym2203_device, write)
-	AM_RANGE(0xf000, 0xf000) AM_WRITE(automat_adpcm_w)
-	AM_RANGE(0x0000, 0xffff) AM_ROM
+	AM_RANGE(0xc800, 0xc801) AM_DEVREADWRITE("2203a", ym2203_device, read, write)
+	AM_RANGE(0xd000, 0xd001) AM_DEVREADWRITE("2203b", ym2203_device, read, write)
+	AM_RANGE(0xd800, 0xd800) AM_READ(sound_command_r)
+	AM_RANGE(0xe000, 0xe000) AM_DEVWRITE("adpcm_select2", ls157_device, ba_w)
+	AM_RANGE(0xe800, 0xe800) AM_WRITE(sound_bankswitch_w)
+	AM_RANGE(0xf000, 0xf000) AM_DEVWRITE("adpcm_select1", ls157_device, ba_w)
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( secretab_s_map, AS_PROGRAM, 8, dec0_automat_state )
+	AM_RANGE(0x0000, 0x7fff) AM_ROM
+	AM_RANGE(0x8000, 0xbfff) AM_ROMBANK("soundbank")
+	AM_RANGE(0xc000, 0xc7ff) AM_RAM
+	AM_RANGE(0xc800, 0xc801) AM_DEVREADWRITE("2203a", ym2203_device, read, write)
+	AM_RANGE(0xd000, 0xd001) AM_DEVREADWRITE("ym3812", ym3812_device, read, write)
+	AM_RANGE(0xd800, 0xd800) AM_READ(sound_command_r)
+	AM_RANGE(0xe000, 0xe000) AM_DEVWRITE("adpcm_select2", ls157_device, ba_w)
+	AM_RANGE(0xe800, 0xe800) AM_WRITE(sound_bankswitch_w)
+	AM_RANGE(0xf000, 0xf000) AM_DEVWRITE("adpcm_select1", ls157_device, ba_w)
 ADDRESS_MAP_END
 
 static ADDRESS_MAP_START( mcu_io_map, AS_IO, 8, dec0_state )
@@ -1358,19 +1385,37 @@ static MACHINE_CONFIG_DERIVED( dec1, dec0_base )
 MACHINE_CONFIG_END
 
 
-WRITE_LINE_MEMBER(dec0_automat_state::automat_vclk_cb)
+READ8_MEMBER(dec0_automat_state::sound_command_r)
 {
-	if (m_automat_msm5205_vclk_toggle == 0)
-	{
-		m_msm->data_w(m_automat_adpcm_byte & 0xf);
-	}
-	else
-	{
-		m_msm->data_w(m_automat_adpcm_byte >> 4);
-		//device->m_audiocpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE); // gives some scratch samples but breaks other sounds too
-	}
+	m_audiocpu->set_input_line(0, CLEAR_LINE);
+	return m_soundlatch->read(space, 0);
+}
+
+WRITE8_MEMBER(dec0_automat_state::sound_bankswitch_w)
+{
+	m_msm1->reset_w(BIT(data, 3));
+	m_msm2->reset_w(BIT(data, 4));
+
+	m_soundbank->set_entry(data & 7);
+}
+
+WRITE_LINE_MEMBER(dec0_automat_state::msm1_vclk_cb)
+{
+	if (!state)
+		return;
+
+	m_adpcm_toggle1 = !m_adpcm_toggle1;
+	m_adpcm_select1->select_w(m_adpcm_toggle1);
+	m_audiocpu->set_input_line(INPUT_LINE_NMI, m_adpcm_toggle1);
+}
+
+WRITE_LINE_MEMBER(dec0_automat_state::msm2_vclk_cb)
+{
+	if (!state)
+		return;
 
-	m_automat_msm5205_vclk_toggle ^= 1;
+	m_adpcm_toggle2 = !m_adpcm_toggle2;
+	m_adpcm_select2->select_w(m_adpcm_toggle2);
 }
 
 
@@ -1418,21 +1463,32 @@ static MACHINE_CONFIG_START( automat, dec0_automat_state )
 
 	MCFG_GENERIC_LATCH_8_ADD("soundlatch")
 
-	MCFG_SOUND_ADD("2203a", YM2203, 1500000)
+	MCFG_SOUND_ADD("2203a", YM2203, 1250000)
 	MCFG_SOUND_ROUTE(0, "mono", 0.90)
 	MCFG_SOUND_ROUTE(1, "mono", 0.90)
 	MCFG_SOUND_ROUTE(2, "mono", 0.90)
 	MCFG_SOUND_ROUTE(3, "mono", 0.35)
 
-	MCFG_SOUND_ADD("2203b", YM2203, 1500000)
+	MCFG_SOUND_ADD("2203b", YM2203, 1250000)
 	MCFG_SOUND_ROUTE(0, "mono", 0.90)
 	MCFG_SOUND_ROUTE(1, "mono", 0.90)
 	MCFG_SOUND_ROUTE(2, "mono", 0.90)
 	MCFG_SOUND_ROUTE(3, "mono", 0.35)
 
-	MCFG_SOUND_ADD("msm", MSM5205, 384000/2)
-	MCFG_MSM5205_VCLK_CB(WRITELINE(dec0_automat_state, automat_vclk_cb))
-	MCFG_MSM5205_PRESCALER_SELECTOR(MSM5205_S48_4B)
+	MCFG_DEVICE_ADD("adpcm_select1", LS157, 0)
+	MCFG_74157_OUT_CB(DEVWRITE8("msm1", msm5205_device, data_w))
+
+	MCFG_DEVICE_ADD("adpcm_select2", LS157, 0)
+	MCFG_74157_OUT_CB(DEVWRITE8("msm2", msm5205_device, data_w))
+
+	MCFG_SOUND_ADD("msm1", MSM5205, 384000)
+	MCFG_MSM5205_VCLK_CB(WRITELINE(dec0_automat_state, msm1_vclk_cb))
+	MCFG_MSM5205_PRESCALER_SELECTOR(MSM5205_S96_4B)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
+
+	MCFG_SOUND_ADD("msm2", MSM5205, 384000)
+	MCFG_MSM5205_VCLK_CB(WRITELINE(dec0_automat_state, msm2_vclk_cb))
+	MCFG_MSM5205_PRESCALER_SELECTOR(MSM5205_S96_4B)
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
 MACHINE_CONFIG_END
 
@@ -1445,7 +1501,7 @@ static MACHINE_CONFIG_START( secretab, dec0_automat_state )
 	MCFG_CPU_VBLANK_INT_DRIVER("screen", dec0_state,  irq6_line_hold)/* VBL */
 
 	MCFG_CPU_ADD("audiocpu", Z80, 3000000)// ?
-	MCFG_CPU_PROGRAM_MAP(automat_s_map)
+	MCFG_CPU_PROGRAM_MAP(secretab_s_map)
 
 	/* video hardware */
 	MCFG_VIDEO_START_OVERRIDE(dec0_state,dec0_nodma)
@@ -1481,23 +1537,30 @@ static MACHINE_CONFIG_START( secretab, dec0_automat_state )
 
 	MCFG_GENERIC_LATCH_8_ADD("soundlatch")
 
-	MCFG_SOUND_ADD("2203a", YM2203, 1500000)
+	MCFG_SOUND_ADD("2203a", YM2203, 1250000)
 	MCFG_SOUND_ROUTE(0, "mono", 0.90)
 	MCFG_SOUND_ROUTE(1, "mono", 0.90)
 	MCFG_SOUND_ROUTE(2, "mono", 0.90)
 	MCFG_SOUND_ROUTE(3, "mono", 0.35)
 
-	MCFG_SOUND_ADD("2203b", YM2203, 1500000)
-	MCFG_SOUND_ROUTE(0, "mono", 0.90)
-	MCFG_SOUND_ROUTE(1, "mono", 0.90)
-	MCFG_SOUND_ROUTE(2, "mono", 0.90)
-	MCFG_SOUND_ROUTE(3, "mono", 0.35)
+	MCFG_SOUND_ADD("ym3812", YM3812, 2500000)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.80)
+
+	MCFG_DEVICE_ADD("adpcm_select1", LS157, 0)
+	MCFG_74157_OUT_CB(DEVWRITE8("msm1", msm5205_device, data_w))
 
-	MCFG_SOUND_ADD("msm", MSM5205, 384000/2)
-	MCFG_MSM5205_VCLK_CB(WRITELINE(dec0_automat_state, automat_vclk_cb))
-	MCFG_MSM5205_PRESCALER_SELECTOR(MSM5205_S48_4B)
+	MCFG_DEVICE_ADD("adpcm_select2", LS157, 0)
+	MCFG_74157_OUT_CB(DEVWRITE8("msm2", msm5205_device, data_w))
+
+	MCFG_SOUND_ADD("msm1", MSM5205, 384000)
+	MCFG_MSM5205_VCLK_CB(WRITELINE(dec0_automat_state, msm1_vclk_cb))
+	MCFG_MSM5205_PRESCALER_SELECTOR(MSM5205_S96_4B)
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
 
+	MCFG_SOUND_ADD("msm2", MSM5205, 384000)
+	MCFG_MSM5205_VCLK_CB(WRITELINE(dec0_automat_state, msm2_vclk_cb))
+	MCFG_MSM5205_PRESCALER_SELECTOR(MSM5205_S96_4B)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
 MACHINE_CONFIG_END
 
 
@@ -2332,13 +2395,14 @@ enjoy..
 
 ROM_START( automat )
 	ROM_REGION( 0x60000, "maincpu", 0 ) /* 68000 code */
-	ROM_LOAD16_BYTE( "5.bin", 0x00000, 0x10000, CRC(fb6faa74) SHA1(0af03c06193b5ba1422571b9504a7f655c608d94) )
-	ROM_LOAD16_BYTE( "2.bin", 0x00001, 0x10000, CRC(7ecf8309) SHA1(59dd50bcb528ece42a67154bcc4f432770420986) )
-	ROM_LOAD16_BYTE( "4.bin", 0x20000, 0x10000, CRC(9d7b79e0) SHA1(e0d901b9b3cd62f7c947da04f7447ebfa88bf44a) )
-	ROM_LOAD16_BYTE( "3.bin", 0x20001, 0x10000, CRC(e655f9c3) SHA1(d5e99d542303d009277ccfc245f877e4e28603c9) )
+	ROM_LOAD16_BYTE( "5.ic50", 0x00000, 0x10000, CRC(fb6faa74) SHA1(0af03c06193b5ba1422571b9504a7f655c608d94) )
+	ROM_LOAD16_BYTE( "2.ic54", 0x00001, 0x10000, CRC(7ecf8309) SHA1(59dd50bcb528ece42a67154bcc4f432770420986) )
+	ROM_LOAD16_BYTE( "4.ic51", 0x20000, 0x10000, CRC(9d7b79e0) SHA1(e0d901b9b3cd62f7c947da04f7447ebfa88bf44a) )
+	ROM_LOAD16_BYTE( "3.ic53", 0x20001, 0x10000, CRC(e655f9c3) SHA1(d5e99d542303d009277ccfc245f877e4e28603c9) )
 
-	ROM_REGION( 0x10000, "audiocpu", 0 )    /* Z80 Sound */
-	ROM_LOAD( "1.bin", 0x00000, 0x10000, CRC(72ea6024) SHA1(debd30219879ec01f43cc116a6cfa17209940ecc) )
+	ROM_REGION( 0x20000, "audiocpu", 0 )    /* Z80 Sound */
+	ROM_LOAD( "1.ic26", 0x00000, 0x10000, CRC(72ea6024) SHA1(debd30219879ec01f43cc116a6cfa17209940ecc) )
+	ROM_RELOAD(        0x10000, 0x10000 ) // IC25 socket unpopulated
 
 	ROM_REGION( 0x40000, "gfxload1", 0 ) /* chars */
 	ROM_LOAD( "8.bin",  0x00000, 0x10000, CRC(dcfffc7a) SHA1(e250626473917d397381210ef536efbc93c46474) ) // y?
@@ -2870,19 +2934,20 @@ from sa_15 to sa_22
 
 ROM_START( secretab )
 	ROM_REGION( 0x60000, "maincpu", 0 ) /* 68000 code */
-	ROM_LOAD16_BYTE( "sa_05.bin",    0x00000, 0x10000, CRC(54869474) SHA1(88c1894d1b6d8dd3d37e97d566aafef9c9409d6e) )
-	ROM_LOAD16_BYTE( "sa_03.bin",    0x00001, 0x10000, CRC(36ab1874) SHA1(baa47c466ab13ac792761531f77ee8e639d19203) )
-	ROM_LOAD16_BYTE( "sa_06.bin",    0x20000, 0x10000, CRC(8e691f23) SHA1(eb08c9539b699af124fcf87be07a33d2d5a71ada) )
-	ROM_LOAD16_BYTE( "sa_04.bin",    0x20001, 0x10000, CRC(c838b205) SHA1(8c7a453ec7a00d4f5bbf9fadba6d551909647ed8) )
+	ROM_LOAD16_BYTE( "sa_05.ic94",   0x00000, 0x10000, CRC(54869474) SHA1(88c1894d1b6d8dd3d37e97d566aafef9c9409d6e) ) // misnumbered; should be IC84
+	ROM_LOAD16_BYTE( "sa_03.ic67",   0x00001, 0x10000, CRC(36ab1874) SHA1(baa47c466ab13ac792761531f77ee8e639d19203) )
+	ROM_LOAD16_BYTE( "sa_06.ic83",   0x20000, 0x10000, CRC(8e691f23) SHA1(eb08c9539b699af124fcf87be07a33d2d5a71ada) )
+	ROM_LOAD16_BYTE( "sa_04.ic66",   0x20001, 0x10000, CRC(c838b205) SHA1(8c7a453ec7a00d4f5bbf9fadba6d551909647ed8) )
 
-	ROM_REGION( 0x10000, "audiocpu", 0 )    /* Sound CPU */
-	ROM_LOAD( "sa_01.bin",      0x00000, 0x10000, CRC(9fdc503b) SHA1(7b258e0734ca88a7d3f574d75116f0fe3b628898) )
+	ROM_REGION( 0x20000, "audiocpu", 0 )    /* Sound CPU */
+	ROM_LOAD( "sa_01.ic41",     0x00000, 0x10000, CRC(9fdc503b) SHA1(7b258e0734ca88a7d3f574d75116f0fe3b628898) )
+	ROM_LOAD( "sa_02.ic40",     0x10000, 0x10000, CRC(439eb5a9) SHA1(8d6baad8a1e89279ef0a378941d3d9b49a606864) ) // both halves identical
 
 	ROM_REGION( 0x40000, "charset", 0 )
-	ROM_LOAD( "sa_08.bin", 0x00000, 0x10000,CRC(4806b951) SHA1(a2fa5b8587132747067d7d64ccfd14129a34ef58) )
-	ROM_LOAD( "sa_12.bin", 0x10000, 0x10000,CRC(f9e2cd5f) SHA1(f2c3f6e763c6f80307e9daee533d316b05cd02c5) )
-	ROM_LOAD( "sa_10.bin", 0x20000, 0x10000,CRC(843c4679) SHA1(871f3e77aa7e628e924a40d06ddec700487e23fb) )
-	ROM_LOAD( "sa_14.bin", 0x30000, 0x10000,CRC(3dac9128) SHA1(f3a2068e90973c1f04f1bbaa209111e3f9669ee0) )
+	ROM_LOAD( "sa_08.ic105", 0x00000, 0x10000,CRC(4806b951) SHA1(a2fa5b8587132747067d7d64ccfd14129a34ef58) )
+	ROM_LOAD( "sa_12.ic156", 0x10000, 0x10000,CRC(f9e2cd5f) SHA1(f2c3f6e763c6f80307e9daee533d316b05cd02c5) )
+	ROM_LOAD( "sa_10.ic138", 0x20000, 0x10000,CRC(843c4679) SHA1(871f3e77aa7e628e924a40d06ddec700487e23fb) )
+	ROM_LOAD( "sa_14.ic188", 0x30000, 0x10000,CRC(3dac9128) SHA1(f3a2068e90973c1f04f1bbaa209111e3f9669ee0) )
 
 	ROM_REGION( 0x20000, "gfx1", ROMREGION_INVERT ) /* chars */
 	ROM_COPY( "charset", 0x00000, 0x00000, 0x8000 )
@@ -2897,23 +2962,20 @@ ROM_START( secretab )
 	ROM_COPY( "charset", 0x38000, 0x18000, 0x8000 )
 
 	ROM_REGION( 0x40000, "gfx3", ROMREGION_INVERT ) /* tiles */
-	ROM_LOAD( "sa_09.bin",      0x00000, 0x10000,CRC(9e412267) SHA1(482cd6e772fa21f15db66c27acf85e8f97f7c5a5) )
-	ROM_LOAD( "sa_11.bin",      0x10000, 0x10000,CRC(e87650db) SHA1(381352428b12fd4a8cd13270009ff7602aa41a0b) )
-	ROM_LOAD( "sa_07.bin",      0x20000, 0x10000,CRC(6ad2e575) SHA1(b6b159cb36e222fe62fc10271602226f027440e4) )
-	ROM_LOAD( "sa_13.bin",      0x30000, 0x10000,CRC(e8601057) SHA1(fd73a36fb84049154248d250ffea68b1ee39a43f) )
+	ROM_LOAD( "sa_09.ic139",     0x00000, 0x10000,CRC(9e412267) SHA1(482cd6e772fa21f15db66c27acf85e8f97f7c5a5) )
+	ROM_LOAD( "sa_11.ic157",     0x10000, 0x10000,CRC(e87650db) SHA1(381352428b12fd4a8cd13270009ff7602aa41a0b) )
+	ROM_LOAD( "sa_07.ic106",     0x20000, 0x10000,CRC(6ad2e575) SHA1(b6b159cb36e222fe62fc10271602226f027440e4) )
+	ROM_LOAD( "sa_13.ic189",     0x30000, 0x10000,CRC(e8601057) SHA1(fd73a36fb84049154248d250ffea68b1ee39a43f) )
 
 	ROM_REGION( 0x80000, "gfx4", 0 ) /* sprites */
-	ROM_LOAD( "sa_20.bin",      0x00000, 0x10000,CRC(447e4f0b) SHA1(97db103e505a6e11eb9bdb3622e4aa3b796a9714) )
-	ROM_LOAD( "sa_19.bin",      0x10000, 0x10000,CRC(d29bc22e) SHA1(ce0935d09f7e94fa32247c86e14a74b73514b29e) )
-	ROM_LOAD( "sa_16.bin",      0x20000, 0x10000,CRC(ff72b838) SHA1(fdc48ecdd2225fc69472313f34973f6add8fb558) )
-	ROM_LOAD( "sa_15.bin",      0x30000, 0x10000,CRC(54fcbc39) SHA1(293a6799193b01424c3eac86cf90cc023aa771db) )
-	ROM_LOAD( "sa_22.bin",      0x40000, 0x10000,CRC(d234cae5) SHA1(0cd07bf087a4da19a5da29785385de9eee52d0fb) )
-	ROM_LOAD( "sa_21.bin",      0x50000, 0x10000,CRC(dc6a38df) SHA1(9043df911389d3f085299f2f2202cab356473a32) )
-	ROM_LOAD( "sa_18.bin",      0x60000, 0x10000,CRC(4f989f00) SHA1(ae7ae6e62e6a516ae3c8ebbeb5e39887c1961add) )
-	ROM_LOAD( "sa_17.bin",      0x70000, 0x10000,CRC(f61972c8) SHA1(fa9ddca3473091b4879171d8f3b302e8f2b45149) )
-
-	ROM_REGION( 0x40000, "oki", 0 ) /* ADPCM samples */
-	ROM_LOAD( "sa_02.bin",      0x00000, 0x10000,CRC(439eb5a9) SHA1(8d6baad8a1e89279ef0a378941d3d9b49a606864) ) // both halves identical
+	ROM_LOAD( "sa_20.ic176",     0x00000, 0x10000,CRC(447e4f0b) SHA1(97db103e505a6e11eb9bdb3622e4aa3b796a9714) )
+	ROM_LOAD( "sa_19.ic177",     0x10000, 0x10000,CRC(d29bc22e) SHA1(ce0935d09f7e94fa32247c86e14a74b73514b29e) )
+	ROM_LOAD( "sa_16.ic180",     0x20000, 0x10000,CRC(ff72b838) SHA1(fdc48ecdd2225fc69472313f34973f6add8fb558) )
+	ROM_LOAD( "sa_15.ic181",     0x30000, 0x10000,CRC(54fcbc39) SHA1(293a6799193b01424c3eac86cf90cc023aa771db) )
+	ROM_LOAD( "sa_22.ic174",     0x40000, 0x10000,CRC(d234cae5) SHA1(0cd07bf087a4da19a5da29785385de9eee52d0fb) )
+	ROM_LOAD( "sa_21.ic175",     0x50000, 0x10000,CRC(dc6a38df) SHA1(9043df911389d3f085299f2f2202cab356473a32) )
+	ROM_LOAD( "sa_18.ic178",     0x60000, 0x10000,CRC(4f989f00) SHA1(ae7ae6e62e6a516ae3c8ebbeb5e39887c1961add) )
+	ROM_LOAD( "sa_17.ic179",     0x70000, 0x10000,CRC(f61972c8) SHA1(fa9ddca3473091b4879171d8f3b302e8f2b45149) )
 ROM_END
 
 
@@ -3331,5 +3393,5 @@ GAME( 1989, ffantasybl, hippodrm, ffantasybl, ffantasybl, dec0_state, ffantasybl
 GAME( 1988, drgninjab2, baddudes, baddudes, drgninja, dec0_state, baddudes, ROT0,   "bootleg", "Dragonninja (bootleg with 68705)", MACHINE_SUPPORTS_SAVE ) // is this the same board as above? (region warning hacked to World, but still shows Japanese text)
 
 // these are different to the above but quite similar to each other
-GAME( 1988, automat,    robocop,  automat,  robocop, dec0_state,  robocop,  ROT0,   "bootleg", "Automat (bootleg of Robocop)", MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE ) // sound rom / music from section z with mods for ADPCM?
-GAME( 1989, secretab,   secretag, secretab, slyspy, dec0_state,   slyspy,   ROT0,   "bootleg", "Secret Agent (bootleg)", MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE )
+GAME( 1988, automat,    robocop,  automat,  robocop,  dec0_state,  robocop, ROT0,   "bootleg", "Automat (bootleg of Robocop)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE ) // sound rom / music from section z with mods for ADPCM?
+GAME( 1989, secretab,   secretag, secretab, slyspy,   driver_device,     0, ROT0,   "bootleg", "Secret Agent (bootleg)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/drivers/dec8.cpp b/src/mame/drivers/dec8.cpp
index 295f254..3912641 100644
--- a/src/mame/drivers/dec8.cpp
+++ b/src/mame/drivers/dec8.cpp
@@ -3210,7 +3210,8 @@ ROM_START( csilver )
 	ROM_CONTINUE(   0x08000, 0x08000 )
 
 	ROM_REGION( 0x1000, "mcu", 0 )    /* ID8751H MCU */
-	ROM_LOAD( "id8751h.mcu", 0x0000, 0x1000, NO_DUMP ) // dx-8.19a ?
+	// 017F: B4 4C 0D : cjne  a,#$4C,$018F   (ID code 0x4c = World version)
+	ROM_LOAD( "id8751h.mcu", 0x0000, 0x1000, CRC(ca663965) SHA1(a5fb7afdfd324761bde4bb90ba12efc9954627af) ) // dx-8.19a ?
 
 	ROM_REGION( 0x08000, "gfx1", 0 )    /* characters */
 	ROM_LOAD( "dx00.3d",  0x00000, 0x08000, CRC(f01ef985) SHA1(d5b823bd7c0efcf3137f8643c5d99a260bed5675) )
@@ -3410,7 +3411,8 @@ ROM_START( srdarwin )
 	ROM_LOAD( "dy04.d7", 0x8000, 0x8000, CRC(2ae3591c) SHA1(f21b06d84e2c3d3895be0812024641fd006e45cf) )
 
 	ROM_REGION( 0x1000, "mcu", 0 )    /* ID8751H MCU */
-	ROM_LOAD( "id8751h.mcu", 0x0000, 0x1000, NO_DUMP )
+	// 0160: B4 6B 0D : cjne  a,#$6B,$0170   (ID code 0x6b = World version)
+	ROM_LOAD( "id8751h.mcu", 0x0000, 0x1000, CRC(11cd6ca4) SHA1(ec70f84228e37f9fc1bda85fa52a009f61c500b2) )
 
 	ROM_REGION( 0x08000, "gfx1", 0 )    /* characters */
 	ROM_LOAD( "dy05.b6", 0x00000, 0x4000, CRC(8780e8a3) SHA1(03ea91fdc5aba8e139201604fb3bf9b69f71f056) )
diff --git a/src/mame/drivers/discoboy.cpp b/src/mame/drivers/discoboy.cpp
index bdb7887..094f359 100644
--- a/src/mame/drivers/discoboy.cpp
+++ b/src/mame/drivers/discoboy.cpp
@@ -44,6 +44,7 @@ Notes:
 #include "emu.h"
 #include "cpu/z80/z80.h"
 #include "machine/gen_latch.h"
+#include "machine/74157.h"
 #include "sound/msm5205.h"
 #include "sound/3812intf.h"
 
@@ -57,6 +58,7 @@ public:
 		m_maincpu(*this, "maincpu"),
 		m_audiocpu(*this, "audiocpu"),
 		m_msm(*this, "msm"),
+		m_adpcm_select(*this, "adpcm_select"),
 		m_gfxdecode(*this, "gfxdecode"),
 		m_palette(*this, "palette"),
 		m_soundlatch(*this, "soundlatch") { }
@@ -65,13 +67,14 @@ public:
 	uint8_t    m_ram_bank;
 	uint8_t    m_gfxbank;
 	uint8_t    m_port_00;
-	int      m_adpcm;
-	uint8_t    m_toggle;
+
+	bool       m_toggle;
 
 	/* devices */
 	required_device<cpu_device> m_maincpu;
 	required_device<cpu_device> m_audiocpu;
 	required_device<msm5205_device> m_msm;
+	required_device<ls157_device> m_adpcm_select;
 	required_device<gfxdecode_device> m_gfxdecode;
 	required_device<palette_device> m_palette;
 	required_device<generic_latch_8_device> m_soundlatch;
@@ -94,7 +97,6 @@ public:
 	DECLARE_READ8_MEMBER(discoboy_ram_att_r);
 	DECLARE_WRITE8_MEMBER(discoboy_ram_att_w);
 	DECLARE_READ8_MEMBER(discoboy_port_06_r);
-	DECLARE_WRITE8_MEMBER(yunsung8_adpcm_w);
 	DECLARE_WRITE8_MEMBER(yunsung8_sound_bankswitch_w);
 	DECLARE_DRIVER_INIT(discoboy);
 	virtual void machine_start() override;
@@ -350,17 +352,11 @@ WRITE8_MEMBER(discoboy_state::yunsung8_sound_bankswitch_w)
 		logerror("%s: Bank %02X\n", machine().describe_context(), data);
 }
 
-WRITE8_MEMBER(discoboy_state::yunsung8_adpcm_w)
-{
-	/* Swap the nibbles */
-	m_adpcm = ((data & 0xf) << 4) | ((data >> 4) & 0xf);
-}
-
 static ADDRESS_MAP_START( sound_map, AS_PROGRAM, 8, discoboy_state )
 	AM_RANGE(0x0000, 0x7fff) AM_ROM
 	AM_RANGE(0x8000, 0xbfff) AM_ROMBANK("sndbank")
 	AM_RANGE(0xe000, 0xe000) AM_WRITE(yunsung8_sound_bankswitch_w)
-	AM_RANGE(0xe400, 0xe400) AM_WRITE(yunsung8_adpcm_w)
+	AM_RANGE(0xe400, 0xe400) AM_DEVWRITE("adpcm_select", ls157_device, ba_w)
 	AM_RANGE(0xec00, 0xec01) AM_DEVWRITE("ymsnd", ym3812_device, write)
 	AM_RANGE(0xf000, 0xf7ff) AM_RAM
 	AM_RANGE(0xf800, 0xf800) AM_DEVREAD("soundlatch", generic_latch_8_device, read)
@@ -467,7 +463,6 @@ void discoboy_state::machine_start()
 	save_item(NAME(m_ram_bank));
 	save_item(NAME(m_port_00));
 	save_item(NAME(m_gfxbank));
-	save_item(NAME(m_adpcm));
 	save_item(NAME(m_toggle));
 }
 
@@ -476,16 +471,17 @@ void discoboy_state::machine_reset()
 	m_ram_bank = 0;
 	m_port_00 = 0;
 	m_gfxbank = 0;
-	m_adpcm = 0x80;
-	m_toggle = 0;
+	m_toggle = false;
 }
 
 WRITE_LINE_MEMBER(discoboy_state::yunsung8_adpcm_int)
 {
-	m_msm->data_w(m_adpcm >> 4);
-	m_adpcm <<= 4;
+	if (!state)
+		return;
 
-	m_toggle ^= 1;
+	m_toggle = !m_toggle;
+	m_adpcm_select->select_w(m_toggle);
+	m_audiocpu->set_input_line(INPUT_LINE_NMI, m_toggle);
 }
 
 static MACHINE_CONFIG_START( discoboy, discoboy_state )
@@ -498,8 +494,6 @@ static MACHINE_CONFIG_START( discoboy, discoboy_state )
 
 	MCFG_CPU_ADD("audiocpu", Z80, XTAL_10MHz/2) /* 5 MHz? */
 	MCFG_CPU_PROGRAM_MAP(sound_map)
-	MCFG_CPU_PERIODIC_INT_DRIVER(discoboy_state, nmi_line_pulse, 32*60)
-
 
 	/* video hardware */
 	MCFG_SCREEN_ADD("screen", RASTER)
@@ -523,6 +517,9 @@ static MACHINE_CONFIG_START( discoboy, discoboy_state )
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.6)
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.6)
 
+	MCFG_DEVICE_ADD("adpcm_select", LS157, 0)
+	MCFG_74157_OUT_CB(DEVWRITE8("msm", msm5205_device, data_w))
+
 	MCFG_SOUND_ADD("msm", MSM5205, XTAL_400kHz)
 	MCFG_MSM5205_VCLK_CB(WRITELINE(discoboy_state, yunsung8_adpcm_int)) /* interrupt function */
 	MCFG_MSM5205_PRESCALER_SELECTOR(MSM5205_S96_4B)      /* 4KHz, 4 Bits */
diff --git a/src/mame/drivers/dmv.cpp b/src/mame/drivers/dmv.cpp
index 1a1a2d4..16dcaaa 100644
--- a/src/mame/drivers/dmv.cpp
+++ b/src/mame/drivers/dmv.cpp
@@ -748,10 +748,10 @@ static MACHINE_CONFIG_START( dmv, dmv_state )
 	MCFG_I8237_OUT_EOP_CB(WRITELINE(dmv_state, dmac_eop))
 	MCFG_I8237_IN_MEMR_CB(READ8(dmv_state, program_r))
 	MCFG_I8237_OUT_MEMW_CB(WRITE8(dmv_state, program_w))
-	MCFG_I8237_IN_IOR_0_CB(LOGGER("DMA CH1", 0))
-	MCFG_I8237_OUT_IOW_0_CB(LOGGER("DMA CH1", 0))
-	MCFG_I8237_IN_IOR_1_CB(LOGGER("DMA CH2", 0))
-	MCFG_I8237_OUT_IOW_1_CB(LOGGER("DMA CH2", 0))
+	MCFG_I8237_IN_IOR_0_CB(LOGGER("Read DMA CH1"))
+	MCFG_I8237_OUT_IOW_0_CB(LOGGER("Write DMA CH1"))
+	MCFG_I8237_IN_IOR_1_CB(LOGGER("Read DMA CH2"))
+	MCFG_I8237_OUT_IOW_1_CB(LOGGER("Write DMA CH2"))
 	MCFG_I8237_IN_IOR_2_CB(DEVREAD8("upd7220", upd7220_device, dack_r))
 	MCFG_I8237_OUT_IOW_2_CB(DEVWRITE8("upd7220", upd7220_device, dack_w))
 	MCFG_I8237_IN_IOR_3_CB(DEVREAD8("i8272", i8272a_device, mdma_r))
diff --git a/src/mame/drivers/dominob.cpp b/src/mame/drivers/dominob.cpp
index cbfa5ad..b2ea6cd 100644
--- a/src/mame/drivers/dominob.cpp
+++ b/src/mame/drivers/dominob.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina, David Haywood
 /***************************************************************************
 
diff --git a/src/mame/drivers/dorachan.cpp b/src/mame/drivers/dorachan.cpp
index 5415e19..e4fb72a 100644
--- a/src/mame/drivers/dorachan.cpp
+++ b/src/mame/drivers/dorachan.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /*
 Dorachan (Dora-Chan ?) (c) 1980 Craul Denshi
diff --git a/src/mame/drivers/dynadice.cpp b/src/mame/drivers/dynadice.cpp
index 67b9f87..b2964b8 100644
--- a/src/mame/drivers/dynadice.cpp
+++ b/src/mame/drivers/dynadice.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina, Pierpaolo Prazzoli
 /*
 Dynamic Dice (??)
diff --git a/src/mame/drivers/dynduke.cpp b/src/mame/drivers/dynduke.cpp
index d9bc9ef..349636b 100644
--- a/src/mame/drivers/dynduke.cpp
+++ b/src/mame/drivers/dynduke.cpp
@@ -197,7 +197,7 @@ static INPUT_PORTS_START( dynduke )
 	PORT_DIPSETTING(      0x0080, DEF_STR( Off ) )
 	PORT_DIPSETTING(      0x0000, DEF_STR( On ) )
 	PORT_BIT( 0x0300, 0x0300, IPT_UNUSED )  /* "SW2:1,2" - Always OFF according to the manual */
-	PORT_DIPNAME( 0x0c00, 0x0400, DEF_STR( Bonus_Life ) ) PORT_DIPLOCATION("SW2:3,4")
+	PORT_DIPNAME( 0x0c00, 0x0400, "Bonus D.Punch" ) PORT_DIPLOCATION("SW2:3,4") // smart bomb extends
 	PORT_DIPSETTING(      0x0c00, "80K 100K+" )
 	PORT_DIPSETTING(      0x0800, "100K 100K+" )
 	PORT_DIPSETTING(      0x0400, "120K 100K+" )
@@ -364,10 +364,10 @@ MACHINE_CONFIG_END
 
 ROM_START( dynduke )
 	ROM_REGION( 0x100000, "maincpu", 0 ) /* v30 main cpu */
-	ROM_LOAD16_BYTE( "1.cd8", 0x0a0000, 0x10000, CRC(a5e2a95a) SHA1(135d57073d826b9cf46fb43dc49439e1400fb021) )
-	ROM_LOAD16_BYTE( "2.cd7", 0x0a0001, 0x10000, CRC(7e51af22) SHA1(b26103c0d41c469d1e2d1e4e89f591c0d9cdb67c) )
-	ROM_LOAD16_BYTE( "3.e8",  0x0c0000, 0x20000, CRC(a56f8692) SHA1(00d86c660efae30c008f8220fdfd397b7d69b2cd) )
-	ROM_LOAD16_BYTE( "4e.e7", 0x0c0001, 0x20000, CRC(384c0635) SHA1(4b9332d8b91426c17a2b2a58633dc6dde526284d) )
+	ROM_LOAD16_BYTE( "1.cd8",   0x0a0000, 0x10000, CRC(a5e2a95a) SHA1(135d57073d826b9cf46fb43dc49439e1400fb021) )
+	ROM_LOAD16_BYTE( "2.cd7",   0x0a0001, 0x10000, CRC(7e51af22) SHA1(b26103c0d41c469d1e2d1e4e89f591c0d9cdb67c) )
+	ROM_LOAD16_BYTE( "dde3.e8", 0x0c0000, 0x20000, CRC(95336279) SHA1(0218640e57d0a6df03ce51f2afad9862d4b13a50) )
+	ROM_LOAD16_BYTE( "dde4.e7", 0x0c0001, 0x20000, CRC(eb2d8fea) SHA1(d6bb718ece9011f7e24ca1c2f70a513e1c13a7a8) )
 
 	ROM_REGION( 0x100000, "slave", 0 ) /* v30 sub cpu */
 	ROM_LOAD16_BYTE( "5.p8", 0x0e0000, 0x10000, CRC(883d319c) SHA1(b0df05bfe342a5289a6368be26317fa879975463) )
@@ -412,10 +412,10 @@ ROM_END
 
 ROM_START( dyndukea )
 	ROM_REGION( 0x100000, "maincpu", 0 ) /* v30 main cpu */
-	ROM_LOAD16_BYTE( "1.cd8",   0x0a0000, 0x10000, CRC(a5e2a95a) SHA1(135d57073d826b9cf46fb43dc49439e1400fb021) )
-	ROM_LOAD16_BYTE( "2.cd7",   0x0a0001, 0x10000, CRC(7e51af22) SHA1(b26103c0d41c469d1e2d1e4e89f591c0d9cdb67c) )
-	ROM_LOAD16_BYTE( "dde3.e8", 0x0c0000, 0x20000, CRC(95336279) SHA1(0218640e57d0a6df03ce51f2afad9862d4b13a50) )
-	ROM_LOAD16_BYTE( "dde4.e7", 0x0c0001, 0x20000, CRC(eb2d8fea) SHA1(d6bb718ece9011f7e24ca1c2f70a513e1c13a7a8) )
+	ROM_LOAD16_BYTE( "1.cd8", 0x0a0000, 0x10000, CRC(a5e2a95a) SHA1(135d57073d826b9cf46fb43dc49439e1400fb021) )
+	ROM_LOAD16_BYTE( "2.cd7", 0x0a0001, 0x10000, CRC(7e51af22) SHA1(b26103c0d41c469d1e2d1e4e89f591c0d9cdb67c) )
+	ROM_LOAD16_BYTE( "3.e8",  0x0c0000, 0x20000, CRC(a56f8692) SHA1(00d86c660efae30c008f8220fdfd397b7d69b2cd) )
+	ROM_LOAD16_BYTE( "4e.e7", 0x0c0001, 0x20000, CRC(384c0635) SHA1(4b9332d8b91426c17a2b2a58633dc6dde526284d) )
 
 	ROM_REGION( 0x100000, "slave", 0 ) /* v30 sub cpu */
 	ROM_LOAD16_BYTE( "5.p8", 0x0e0000, 0x10000, CRC(883d319c) SHA1(b0df05bfe342a5289a6368be26317fa879975463) )
@@ -653,9 +653,9 @@ ROM_END
 
 /* Game Drivers */
 
-GAME( 1989, dynduke,  0,       dynduke, dynduke, driver_device, 0, ROT0, "Seibu Kaihatsu",                  "Dynamite Duke (Europe set 1)", MACHINE_SUPPORTS_SAVE )
-GAME( 1989, dyndukea, dynduke, dynduke, dynduke, driver_device, 0, ROT0, "Seibu Kaihatsu",                  "Dynamite Duke (Europe set 2)", MACHINE_SUPPORTS_SAVE )
-GAME( 1989, dyndukej, dynduke, dynduke, dynduke, driver_device, 0, ROT0, "Seibu Kaihatsu",                  "Dynamite Duke (Japan)", MACHINE_SUPPORTS_SAVE )
-GAME( 1989, dyndukeu, dynduke, dynduke, dynduke, driver_device, 0, ROT0, "Seibu Kaihatsu (Fabtek license)", "Dynamite Duke (US)", MACHINE_SUPPORTS_SAVE )
-GAME( 1989, dbldynj,  0,       dbldyn,  dynduke, driver_device, 0, ROT0, "Seibu Kaihatsu",                  "The Double Dynamites (Japan)", MACHINE_SUPPORTS_SAVE )
-GAME( 1989, dbldynu,  dbldynj, dynduke, dynduke, driver_device, 0, ROT0, "Seibu Kaihatsu (Fabtek license)", "The Double Dynamites (US)", MACHINE_SUPPORTS_SAVE )
+GAME( 1989, dynduke,  0,       dynduke, dynduke, driver_device, 0, ROT0, "Seibu Kaihatsu",                  "Dynamite Duke (Europe set 1 03SEP89)", MACHINE_SUPPORTS_SAVE )
+GAME( 1989, dyndukea, dynduke, dynduke, dynduke, driver_device, 0, ROT0, "Seibu Kaihatsu",                  "Dynamite Duke (Europe set 2 25JUL89)", MACHINE_SUPPORTS_SAVE )
+GAME( 1989, dyndukej, dynduke, dynduke, dynduke, driver_device, 0, ROT0, "Seibu Kaihatsu",                  "Dynamite Duke (Japan 03SEP89)", MACHINE_SUPPORTS_SAVE )
+GAME( 1989, dyndukeu, dynduke, dynduke, dynduke, driver_device, 0, ROT0, "Seibu Kaihatsu (Fabtek license)", "Dynamite Duke (US 25JUL89)", MACHINE_SUPPORTS_SAVE )
+GAME( 1989, dbldynj,  0,       dbldyn,  dynduke, driver_device, 0, ROT0, "Seibu Kaihatsu",                  "The Double Dynamites (Japan 13NOV89)", MACHINE_SUPPORTS_SAVE )
+GAME( 1989, dbldynu,  dbldynj, dynduke, dynduke, driver_device, 0, ROT0, "Seibu Kaihatsu (Fabtek license)", "The Double Dynamites (US 13NOV89)", MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/drivers/eolith.cpp b/src/mame/drivers/eolith.cpp
index eb8a7b6..96244b2 100644
--- a/src/mame/drivers/eolith.cpp
+++ b/src/mame/drivers/eolith.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina,Pierpaolo Prazzoli
 /********************************************************************
  Eolith 32 bits hardware: Gradation 2D system
diff --git a/src/mame/drivers/epos.cpp b/src/mame/drivers/epos.cpp
index 2ed9fe2..70844a3 100644
--- a/src/mame/drivers/epos.cpp
+++ b/src/mame/drivers/epos.cpp
@@ -28,8 +28,6 @@
       halfs of the palette are identical, this is not an issue.  See $039c.
       The other games have a different color test, not using the busy loop.
 
-    - Find out how Beastie Feastie's 2nd player inputs work.
-
     - Fix flip screen support for The Dealer and Beastie Feastie.
 
 ***************************************************************************/
@@ -101,6 +99,18 @@ static ADDRESS_MAP_START( dealer_io_map, AS_IO, 8, epos_state )
 	AM_RANGE(0x40, 0x40) AM_DEVWRITE("watchdog", watchdog_timer_device, reset_w)
 ADDRESS_MAP_END
 
+READ8_MEMBER(epos_state::read_prta)
+{
+	uint8_t data = 0xff;
+
+	if (!BIT(m_input_multiplex, 0))
+		data &= m_inputs[0]->read();
+
+	if (!BIT(m_input_multiplex, 1))
+		data &= m_inputs[1]->read();
+
+	return data;
+}
 
 /*
    ROMs U01-U03 are checked with the same code in a loop.
@@ -110,6 +120,7 @@ ADDRESS_MAP_END
 WRITE8_MEMBER(epos_state::write_prtc)
 {
 	membank("bank2")->set_entry(data & 0x01);
+	m_input_multiplex = (data >> 5) & 3;
 }
 
 /*************************************
@@ -343,13 +354,23 @@ static INPUT_PORTS_START( dealer )
 	PORT_BIT( 0x80, IP_ACTIVE_LOW,  IPT_UNKNOWN )
 
 	PORT_START("INPUTS")
-	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) //cancel
-	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) //draw
-	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON3 ) //stand
+	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 )
+	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 )
+	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON3 )
 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON4 )
-	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON5 ) //play
-	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON6 )
-	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN1 ) //coin in
+	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON5 )
+	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
+	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
+	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
+
+	PORT_START("INPUTS2")
+	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_POKER_CANCEL )
+	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_GAMBLE_DEAL ) PORT_NAME( "Draw" )
+	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_GAMBLE_STAND )
+	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN )
+	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_GAMBLE_BET ) PORT_NAME( "Play" )
+	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
+	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN1 )
 	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_SERVICE )
 INPUT_PORTS_END
 
@@ -363,7 +384,16 @@ static INPUT_PORTS_START( beastf )
 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_4WAY
 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 )
 	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 )
-	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN1 )
+	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_START1 )
+	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START2 )
+
+	PORT_MODIFY("INPUTS2")
+	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_4WAY PORT_PLAYER(2)
+	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_4WAY PORT_PLAYER(2)
+	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_4WAY PORT_PLAYER(2)
+	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_4WAY PORT_PLAYER(2)
+	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
+	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2)
 INPUT_PORTS_END
 
 /*************************************
@@ -376,12 +406,14 @@ MACHINE_START_MEMBER(epos_state,epos)
 {
 	save_item(NAME(m_palette));
 	save_item(NAME(m_counter));
+	save_item(NAME(m_input_multiplex));
 }
 
 void epos_state::machine_reset()
 {
 	m_palette = 0;
 	m_counter = 0;
+	m_input_multiplex = 3;
 }
 
 
@@ -431,7 +463,7 @@ static MACHINE_CONFIG_START( dealer, epos_state )
 	MCFG_CPU_VBLANK_INT_DRIVER("screen", epos_state,  irq0_line_hold)
 
 	MCFG_DEVICE_ADD("ppi8255", I8255A, 0)
-	MCFG_I8255_IN_PORTA_CB(IOPORT("INPUTS"))
+	MCFG_I8255_IN_PORTA_CB(READ8(epos_state, read_prta))
 	MCFG_I8255_OUT_PORTC_CB(WRITE8(epos_state, write_prtc))
 
 	MCFG_MACHINE_START_OVERRIDE(epos_state,dealer)
diff --git a/src/mame/drivers/equites.cpp b/src/mame/drivers/equites.cpp
index cacf60c..4c10833 100644
--- a/src/mame/drivers/equites.cpp
+++ b/src/mame/drivers/equites.cpp
@@ -169,8 +169,6 @@ TODO:
 - bassline imperfect. This is just the square wave output of the 5232 at the moment.
   It should go through analog stages.
 
-- properly emulate the 8155 on the sound board.
-
 - implement low-pass filters on the DAC output
 
 - the purpose of the sound PROM is unclear. From the schematics, it seems it
@@ -365,6 +363,7 @@ D
 #include "cpu/alph8201/alph8201.h"
 #include "cpu/i8085/i8085.h"
 #include "cpu/m68000/m68000.h"
+#include "machine/i8155.h"
 #include "machine/nvram.h"
 #include "machine/watchdog.h"
 #include "sound/ay8910.h"
@@ -385,9 +384,10 @@ D
 /******************************************************************************/
 // Sound
 
-TIMER_CALLBACK_MEMBER(equites_state::equites_nmi_callback)
+WRITE_LINE_MEMBER(equites_state::equites_8155_timer_pulse)
 {
-	m_audiocpu->set_input_line(INPUT_LINE_NMI, ASSERT_LINE);
+	if (!state) // active low
+		m_audiocpu->set_input_line(INPUT_LINE_NMI, ASSERT_LINE);
 }
 
 TIMER_CALLBACK_MEMBER(equites_state::equites_frq_adjuster_callback)
@@ -518,12 +518,35 @@ WRITE8_MEMBER(equites_state::equites_dac_latch_w)
 	equites_update_dac();
 }
 
+WRITE8_MEMBER(equites_state::equites_8155_porta_w)
+{
+	m_eq8155_port_a = data;
+	m_msm->set_output_gain(0, (data >> 4) / 15.0);  /* group1 from msm5232 */
+	m_msm->set_output_gain(1, (data >> 4) / 15.0);  /* group1 from msm5232 */
+	m_msm->set_output_gain(2, (data >> 4) / 15.0);  /* group1 from msm5232 */
+	m_msm->set_output_gain(3, (data >> 4) / 15.0);  /* group1 from msm5232 */
+	m_msm->set_output_gain(4, (data & 0x0f) / 15.0);    /* group2 from msm5232 */
+	m_msm->set_output_gain(5, (data & 0x0f) / 15.0);    /* group2 from msm5232 */
+	m_msm->set_output_gain(6, (data & 0x0f) / 15.0);    /* group2 from msm5232 */
+	m_msm->set_output_gain(7, (data & 0x0f) / 15.0);    /* group2 from msm5232 */
+}
+
 WRITE8_MEMBER(equites_state::equites_8155_portb_w)
 {
 	m_eq8155_port_b = data;
 	equites_update_dac();
 }
 
+WRITE8_MEMBER(equites_state::equites_8155_portc_w)
+{
+	m_eq8155_port_c = data;
+	m_msm->set_output_gain(8, (data & 0x0f) / 15.0);    /* SOLO  8' from msm5232 */
+	if (data & 0x20)
+		m_msm->set_output_gain(9, (data & 0x0f) / 15.0);    /* SOLO 16' from msm5232 */
+	else
+		m_msm->set_output_gain(9, 0);   /* SOLO 16' from msm5232 */
+}
+
 WRITE_LINE_MEMBER(equites_state::equites_msm5232_gate)
 {
 }
@@ -555,47 +578,6 @@ TIMER_DEVICE_CALLBACK_MEMBER(equites_state::splndrbt_scanline)
 		m_maincpu->set_input_line(2, HOLD_LINE);
 }
 
-WRITE8_MEMBER(equites_state::equites_8155_w)
-{
-	// FIXME proper 8155 emulation must be implemented
-	switch( offset )
-	{
-		case 0: //logerror( "8155 Command register write %x, timer command = %x, interrupt enable = %x, ports = %x\n", data, (data >> 6) & 3, (data >> 4) & 3, data & 0xf );
-			if (((data >> 6) & 3) == 3)
-				m_nmi_timer->adjust(attotime::from_hz(XTAL_6_144MHz/2 / m_timer_count), 0, attotime::from_hz(XTAL_6_144MHz/2 / m_timer_count));
-			break;
-		case 1: //logerror( "8155 I/O Port A write %x\n", data );
-			m_eq8155_port_a = data;
-			m_msm->set_output_gain(0, (data >> 4) / 15.0);  /* group1 from msm5232 */
-			m_msm->set_output_gain(1, (data >> 4) / 15.0);  /* group1 from msm5232 */
-			m_msm->set_output_gain(2, (data >> 4) / 15.0);  /* group1 from msm5232 */
-			m_msm->set_output_gain(3, (data >> 4) / 15.0);  /* group1 from msm5232 */
-			m_msm->set_output_gain(4, (data & 0x0f) / 15.0);    /* group2 from msm5232 */
-			m_msm->set_output_gain(5, (data & 0x0f) / 15.0);    /* group2 from msm5232 */
-			m_msm->set_output_gain(6, (data & 0x0f) / 15.0);    /* group2 from msm5232 */
-			m_msm->set_output_gain(7, (data & 0x0f) / 15.0);    /* group2 from msm5232 */
-			break;
-		case 2: //logerror( "8155 I/O Port B write %x\n", data );
-			equites_8155_portb_w(space, 0, data);
-			break;
-		case 3: //logerror( "8155 I/O Port C (or control) write %x\n", data );
-			m_eq8155_port_c = data;
-			m_msm->set_output_gain(8, (data & 0x0f) / 15.0);    /* SOLO  8' from msm5232 */
-			if (data & 0x20)
-				m_msm->set_output_gain(9, (data & 0x0f) / 15.0);    /* SOLO 16' from msm5232 */
-			else
-				m_msm->set_output_gain(9, 0);   /* SOLO 16' from msm5232 */
-
-			break;
-		case 4: //logerror( "8155 Timer low 8 bits write %x\n", data );
-			m_timer_count = (m_timer_count & 0xff00) | data;
-			break;
-		case 5: //logerror( "8155 Timer high 6 bits write %x, timer mode %x\n", data & 0x3f, (data >> 6) & 3);
-			m_timer_count = (m_timer_count & 0x00ff) | ((data & 0x3f) << 8);
-			break;
-	}
-}
-
 
 
 /******************************************************************************/
@@ -717,11 +699,11 @@ static ADDRESS_MAP_START( sound_map, AS_PROGRAM, 8, equites_state )
 	AM_RANGE(0xc0d0, 0xc0d0) AM_WRITE(equites_dac_latch_w)  // followed by 1 (and usually 0) on 8155 port B
 	AM_RANGE(0xc0e0, 0xc0e0) AM_WRITE(equites_dac_latch_w)  // followed by 2 (and usually 0) on 8155 port B
 	AM_RANGE(0xc0f8, 0xc0ff) AM_WRITE(equites_c0f8_w)
-	AM_RANGE(0xe000, 0xe0ff) AM_RAM
+	AM_RANGE(0xe000, 0xe0ff) AM_DEVREADWRITE("audio8155", i8155_device, memory_r, memory_w)
 ADDRESS_MAP_END
 
 static ADDRESS_MAP_START( sound_portmap, AS_IO, 8, equites_state )
-	AM_RANGE(0x00e0, 0x00e5) AM_WRITE(equites_8155_w)
+	AM_RANGE(0x00e0, 0x00e7) AM_DEVREADWRITE("audio8155", i8155_device, io_r, io_w)
 ADDRESS_MAP_END
 
 
@@ -1056,6 +1038,12 @@ static MACHINE_CONFIG_FRAGMENT( common_sound )
 	MCFG_CPU_PROGRAM_MAP(sound_map)
 	MCFG_CPU_IO_MAP(sound_portmap)
 
+	MCFG_DEVICE_ADD("audio8155", I8155, XTAL_6_144MHz/2)
+	MCFG_I8155_OUT_PORTA_CB(WRITE8(equites_state, equites_8155_porta_w))
+	MCFG_I8155_OUT_PORTB_CB(WRITE8(equites_state, equites_8155_portb_w))
+	MCFG_I8155_OUT_PORTC_CB(WRITE8(equites_state, equites_8155_portc_w))
+	MCFG_I8155_OUT_TIMEROUT_CB(WRITELINE(equites_state, equites_8155_timer_pulse))
+
 	/* sound hardware */
 	MCFG_SPEAKER_STANDARD_MONO("speaker")
 
@@ -1133,8 +1121,6 @@ void equites_state::machine_start()
 	save_item(NAME(m_timer_count));
 	save_item(NAME(m_gekisou_unknown_bit));
 
-	m_nmi_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(equites_state::equites_nmi_callback), this));
-
 	m_adjuster_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(equites_state::equites_frq_adjuster_callback), this));
 	m_adjuster_timer->adjust(attotime::from_hz(60), 0, attotime::from_hz(60));
 }
diff --git a/src/mame/drivers/ertictac.cpp b/src/mame/drivers/ertictac.cpp
index f0c0c2c..2d71557 100644
--- a/src/mame/drivers/ertictac.cpp
+++ b/src/mame/drivers/ertictac.cpp
@@ -105,7 +105,7 @@ static INPUT_PORTS_START( ertictac )
 	PORT_DIPNAME( 0x04, 0x04, "Test Mode" )     PORT_DIPLOCATION("DSW1:1")
 	PORT_DIPSETTING(    0x04, DEF_STR( No ) )
 	PORT_DIPSETTING(    0x00, DEF_STR( Yes ) )
-	PORT_DIPNAME( 0x08, 0x00, "Music" )     PORT_DIPLOCATION("DSW1:4")
+	PORT_DIPNAME( 0x08, 0x08, "Music" )     PORT_DIPLOCATION("DSW1:4")
 	PORT_DIPSETTING(    0x00, DEF_STR( No ) )
 	PORT_DIPSETTING(    0x08, DEF_STR( Yes ) )
 	PORT_DIPNAME( 0x30, 0x30, "Game Timing" )   PORT_DIPLOCATION("DSW1:5,6")
@@ -228,10 +228,7 @@ static MACHINE_CONFIG_START( ertictac, ertictac_state )
 //  MCFG_AAKART_ADD("kart", XTAL_24MHz/3) // TODO: frequency
 
 	MCFG_SCREEN_ADD("screen", RASTER)
-	MCFG_SCREEN_REFRESH_RATE(60)
-	MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */
-	MCFG_SCREEN_SIZE(1280, 1024)
-	MCFG_SCREEN_VISIBLE_AREA(0, 1280-1, 0, 1024-1)
+	MCFG_SCREEN_RAW_PARAMS(XTAL_16MHz,1024,0,735,624/2,0,292) // RiscOS 3 default screen settings
 	MCFG_SCREEN_UPDATE_DRIVER(archimedes_state, screen_update)
 
 	MCFG_PALETTE_ADD("palette", 0x200)
diff --git a/src/mame/drivers/esq5505.cpp b/src/mame/drivers/esq5505.cpp
index b09ea85..a1703e2 100644
--- a/src/mame/drivers/esq5505.cpp
+++ b/src/mame/drivers/esq5505.cpp
@@ -923,6 +923,22 @@ ROM_START( sqrack )
 	ROM_REGION(0x80000, "nibbles", ROMREGION_ERASE00)
 ROM_END
 
+ROM_START( sq2 )
+	ROM_REGION(0x40000, "osrom", 0)
+	ROM_LOAD16_BYTE( "sq232_2.03_9193_lower.u27", 0x000000, 0x010000, CRC(e37fbc2c) SHA1(4a74f3540756745073c8768b384905db03da47c0) )
+	ROM_LOAD16_BYTE( "sq232_2.03_cbcd_upper.u32", 0x000001, 0x020000, CRC(5a7dc228) SHA1(d25adecc0dbba93a094c49fae105dcc7aad317f1) )
+
+	ROM_REGION(0x200000, "waverom", 0)
+	ROM_LOAD16_BYTE( "sq1-u25.bin",  0x000001, 0x080000, CRC(26312451) SHA1(9f947a11592fd8420fc581914bf16e7ade75390c) )
+	ROM_LOAD16_BYTE( "sq1-u26.bin",  0x100001, 0x080000, CRC(2edaa9dc) SHA1(72fead505c4f44e5736ff7d545d72dfa37d613e2) )
+
+	ROM_REGION(0x200000, "waverom2", ROMREGION_ERASE00) // BS=1 region (16-bit)
+	ROM_LOAD( "rom2.u39",     0x000000, 0x100000, CRC(8d1b5e91) SHA1(12991083a6c574133a1a799813fa4573a33d2297) )
+	ROM_LOAD( "rom3.u38",     0x100000, 0x100000, CRC(cb9875ce) SHA1(82021bdc34953e9be97d45746a813d7882250ae0) )
+
+	ROM_REGION(0x80000, "nibbles", ROMREGION_ERASE00)
+ROM_END
+
 ROM_START( eps )
 	ROM_REGION(0x20000, "osrom", 0)
 	ROM_LOAD16_BYTE( "eps-l.bin",    0x000000, 0x008000, CRC(382beac1) SHA1(110e31edb03fcf7bbde3e17423b21929e5b32db2) )
@@ -999,4 +1015,5 @@ CONS( 1990, eps16p,eps, 0, eps,   vfx, esq5505_state, eps,    "Ensoniq", "EPS-16
 CONS( 1990, sd1,   0, 0,   vfxsd, vfx, esq5505_state, denib,  "Ensoniq", "SD-1 (21 voice)", MACHINE_NOT_WORKING )  // 2x40 VFD
 CONS( 1990, sq1,   0, 0,   sq1,   sq1, esq5505_state, sq1,    "Ensoniq", "SQ-1", MACHINE_NOT_WORKING )      // 2x16 LCD
 CONS( 1990, sqrack,sq1, 0, sq1,   sq1, esq5505_state, sq1,    "Ensoniq", "SQ-Rack", MACHINE_NOT_WORKING )   // 2x16 LCD
+CONS( 1991, sq2,   0, 0,   sq1,   sq1, esq5505_state, sq1,    "Ensoniq", "SQ-2", MACHINE_NOT_WORKING )      // 2x16 LCD
 CONS( 1991, sd132, sd1,0,  vfx32, vfx, esq5505_state, denib,  "Ensoniq", "SD-1 (32 voice)", MACHINE_NOT_WORKING )  // 2x40 VFD
diff --git a/src/mame/drivers/esripsys.cpp b/src/mame/drivers/esripsys.cpp
index 5251738..e8dc1a1 100644
--- a/src/mame/drivers/esripsys.cpp
+++ b/src/mame/drivers/esripsys.cpp
@@ -699,8 +699,7 @@ static MACHINE_CONFIG_START( esripsys, esripsys_state )
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "speaker", 1.0)
 
 	/* 6840 PTM */
-	MCFG_DEVICE_ADD("6840ptm", PTM6840, 0)
-	MCFG_PTM6840_INTERNAL_CLOCK(XTAL_8MHz / 4)
+	MCFG_DEVICE_ADD("6840ptm", PTM6840, XTAL_8MHz / 4)
 	MCFG_PTM6840_EXTERNAL_CLOCKS(0, 0, 0)
 	MCFG_PTM6840_IRQ_CB(WRITELINE(esripsys_state, ptm_irq))
 MACHINE_CONFIG_END
diff --git a/src/mame/drivers/expro02.cpp b/src/mame/drivers/expro02.cpp
index 09dc31b..34911ec 100644
--- a/src/mame/drivers/expro02.cpp
+++ b/src/mame/drivers/expro02.cpp
@@ -1650,6 +1650,23 @@ ROM_START( wownfant)
 	ROM_LOAD( "ep-4001 42750001 u1.bin",    0x80000, 0x80000, CRC(864167c2) SHA1(c454b26b6dea993e6bd64546f92beef05e46d7d7) )
 ROM_END
 
+ROM_START( missw02)
+	ROM_REGION( 0x500000, "maincpu", 0 )    /* 68000 code */
+	ROM_LOAD16_BYTE( "8.u81",      0x000000, 0x80000,  CRC(316666d0) SHA1(0ebebc55b49c1d00adac2b04bcfe9cfb317e8e74) ) // stickered as Miss World 2002 Rev.A
+	ROM_LOAD16_BYTE( "7.u80",      0x000001, 0x80000,  CRC(d61f4d18) SHA1(caef5fb221cafc354875ef5b68e84419f91c0db7) )
+	ROM_LOAD16_WORD_SWAP( "3.bin", 0x100000, 0x200000, CRC(fdfe36ba) SHA1(128277e44e2368267e097bb3510c797cc690d1ff) )
+	ROM_LOAD16_WORD_SWAP( "4.bin", 0x300000, 0x200000, CRC(aa769a81) SHA1(2beb6da9327ddce7bec934bcf610061fc3b9ab09) )
+
+	ROM_REGION( 0x100000, "gfx1", 0 )   /* sprites */
+	ROM_LOAD( "6.u113", 0x00000, 0x80000, CRC(3e77ca1f) SHA1(f946e65a29bc02b89c02b2a869578d38cfe7e2d0) ) // same as wowfant
+	ROM_LOAD( "5.u112", 0x80000, 0x80000, CRC(ead3411d) SHA1(ee1b071e4a556b66ecdedcdc7e1ee60851c0ddb0) )
+
+	ROM_REGION( 0x100000, "oki", 0 )    /* OKIM6295 samples */
+	/* 00000-2ffff is fixed, 30000-3ffff is bank switched from all the ROMs */
+	ROM_LOAD( "2.u4", 0x00000, 0x80000, CRC(06dc889e) SHA1(726561ff01bbde43669293a6ff7ee22b048b4118) ) // these 2 same as wowfant
+	ROM_LOAD( "1.u1", 0x80000, 0x80000, CRC(864167c2) SHA1(c454b26b6dea993e6bd64546f92beef05e46d7d7) )
+ROM_END
+
 ROM_START( galhustl ) // An original PCB has been seen with genuine AFEGA labels
 	ROM_REGION( 0x100000, "maincpu", 0 ) /* 68000 Code */
 	ROM_LOAD16_BYTE( "ue17.3", 0x00000, 0x80000, CRC(b2583dbb) SHA1(536f4aa2246ec816c4f270f9d42acc090718ee8b) ) // Also found as AFEGA 3
@@ -1824,27 +1841,28 @@ GAME( 1994, fantasiaa, fantasia, comad,    fantasia, expro02_state, expro02, ROT
 /* subsequent releases remove the encrypted tile (View2 layer) but leave the unused writes to it in the program code */
 GAME( 1994, fantasian,fantasia, fantasia,  fantasiaa, driver_device, 0, ROT90, "Comad & New Japan System", "Fantasia (940803 PCB)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE )
 
-GAME( 1994, supmodel, 0,        supmodel, fantasiaa, driver_device, 0, ROT90, "Comad & New Japan System", "Super Model",MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE )
+GAME( 1994, supmodel, 0,        supmodel, fantasiaa, driver_device, 0, ROT90, "Comad & New Japan System", "Super Model",MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE ) // "C" nudity level
 
 GAME( 1995, newfant,  0,        fantasia, fantasiaa, driver_device, 0, ROT90, "Comad & New Japan System", "New Fantasia (1995 copyright)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE ) // the only difference between the two is the gfx rom containing the copyright
 GAME( 1994, newfanta, newfant,  fantasia, fantasiaa, driver_device, 0, ROT90, "Comad & New Japan System", "New Fantasia (1994 copyright)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE )
-GAME( 1995, fantsy95, newfant,  fantasia, fantasiaa, driver_device, 0, ROT90, "Hi-max Technology Inc.",   "Fantasy '95", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE )
+GAME( 1995, fantsy95, newfant,  fantasia, fantasiaa, driver_device, 0, ROT90, "Hi-max Technology Inc.",   "Fantasy '95", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE ) // "C" nudity level
 
 // the PCB label (A/B) could be related to the 3 different levels of nudity Comad offered
-GAME( 1996, missw96,  0,        fantasia, missw96,   driver_device, 0, ROT0,  "Comad",                    "Miss World '96 (Nude) (C-3000A PCB, set 1)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE )
-GAME( 1996, missw96a, missw96,  fantasia, missw96,   driver_device, 0, ROT0,  "Comad",                    "Miss World '96 (Nude) (C-3000A PCB, set 2)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE )
-GAME( 1996, missw96b, missw96,  fantasia, missw96,   driver_device, 0, ROT0,  "Comad",                    "Miss World '96 (Nude) (C-3000A PCB, set 3)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE )
-GAME( 1996, missw96c, missw96,  fantasia, missw96,   driver_device, 0, ROT0,  "Comad",                    "Miss World '96 (Nude) (C-3000B PCB)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE )
+GAME( 1996, missw96,  0,        fantasia, missw96,   driver_device, 0, ROT0,  "Comad",                    "Miss World '96 (Nude) (C-3000A PCB, set 1)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE ) // "A" nudity level
+GAME( 1996, missw96a, missw96,  fantasia, missw96,   driver_device, 0, ROT0,  "Comad",                    "Miss World '96 (Nude) (C-3000A PCB, set 2)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE ) // "A" nudity level
+GAME( 1996, missw96b, missw96,  fantasia, missw96,   driver_device, 0, ROT0,  "Comad",                    "Miss World '96 (Nude) (C-3000A PCB, set 3)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE ) // "A" nudity level
+GAME( 1996, missw96c, missw96,  fantasia, missw96,   driver_device, 0, ROT0,  "Comad",                    "Miss World '96 (Nude) (C-3000B PCB)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE )        // "B" nudity level
 
 GAME( 1996, missmw96, missw96,  fantasia, missw96,   driver_device, 0, ROT0,  "Comad",                    "Miss Mister World '96 (Nude)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE )
 
 GAME( 1996, smissw,   0,        smissw,   missw96,   driver_device, 0, ROT0,  "Comad",                    "Super Miss World", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE ) // 951127 PCB
 
-GAME( 1997, fantsia2, 0,        fantsia2, missw96,   driver_device, 0, ROT0,  "Comad",                    "Fantasia II (Explicit)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE )
-GAME( 1997, fantsia2a,fantsia2, fantsia2, missw96,   driver_device, 0, ROT0,  "Comad",                    "Fantasia II (Less Explicit)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE )
-GAME( 1998, fantsia2n,fantsia2, fantsia2, missw96,   driver_device, 0, ROT0,  "Comad",                    "Fantasia II (1998)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE )
+GAME( 1997, fantsia2, 0,        fantsia2, missw96,   driver_device, 0, ROT0,  "Comad",                    "Fantasia II (Explicit)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE )      // "A" nudity level
+GAME( 1997, fantsia2a,fantsia2, fantsia2, missw96,   driver_device, 0, ROT0,  "Comad",                    "Fantasia II (Less Explicit)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE ) // "B" nudity level
+GAME( 1998, fantsia2n,fantsia2, fantsia2, missw96,   driver_device, 0, ROT0,  "Comad",                    "Fantasia II (1998)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE )          // "A" nudity level
 
-GAME( 2002, wownfant, 0,        fantsia2, missw96,   driver_device, 0, ROT0,  "Comad",                    "WOW New Fantasia", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE )
+GAME( 2002, wownfant, 0,        fantsia2, missw96,   driver_device, 0, ROT0,  "Comad",                    "WOW New Fantasia", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE ) // "B" nudity level
+GAME( 2002, missw02,  0,        fantsia2, missw96,   driver_device, 0, ROT0,  "Daigom",                   "Miss World 2002", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE )  // "A" nudity level
 
 GAME( 1996, pgalvip,  0,        galhustl, galhustl,  driver_device, 0, ROT0,  "ACE International / Afega","Pocket Gals V.I.P (set 1)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE ) // roms were all AFEGA stickered, select screen seems wrong? maybe not a final version.
 GAME( 1997, pgalvipa, pgalvip,  galhustl, galhustl,  driver_device, 0, ROT0,  "<unknown>",                "Pocket Gals V.I.P (set 2)", MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/drivers/fccpu20.cpp b/src/mame/drivers/fccpu20.cpp
new file mode 100644
index 0000000..0749632
--- /dev/null
+++ b/src/mame/drivers/fccpu20.cpp
@@ -0,0 +1,287 @@
+// license:BSD-3-Clause
+// copyright-holders:Joakim Larsson Edstrom
+/***************************************************************************
+ *
+ *  Force SYS68K CPU-20 VME SBC drivers
+ *
+ *  24/12/2016
+ *
+ * Thanks to Al Kossow and his site http://www.bitsavers.org/ I got the information
+ * required to start the work with this driver.
+ *
+ *
+ *       ||
+ * ||    ||  CPU-20
+ * ||||--||_____________________________________________________________
+ * ||||--||                                                             |
+ * ||    ||                                                           _ |__
+ *       ||                                                          | |   |
+ *       ||                                                          | |   |
+ *       ||                                                          | |   |
+ *       ||                                                          | |   |
+ *       ||                                                          | |   |
+ *       ||                                                          | |   |
+ *       ||                                                          | |VME|
+ *       ||                                                          | |   |
+ *       ||                                                          | |P1 |
+ *       ||                                                          | |   |
+ *       ||                                                          | |   |
+ *       ||                                                          | |   |
+ *       ||                                                          | |   |
+ *       ||                                                          | |   |
+ *       ||                                                          | |   |
+ *       ||                                                          |_|   |
+ *       ||                                                            |___|
+ *       ||                                                            |
+ *       ||                                                            |
+ *       ||                                                            |
+ *       ||                                                            |
+ *       ||                                                            |
+ *       ||                                                            |
+ *       ||                                                            |
+ *       ||                                                            |
+ *       ||                                                            |___
+ *       ||                                                           _|   |
+ *       ||                                                          | |   |
+ *       ||                                                          | |   |
+ *       ||                                                          | |   |
+ *       ||                                                          | |   |
+ *       ||                                                          | |VME|
+ *       ||                                                          | |   |
+ *       ||                                                          | |P2 |
+ *       ||                                                          | |   |
+ *       ||                                                          | |   |
+ *       ||                                                          | |   |
+ *       ||                                                          | |   |
+ *       ||                                                          | |   |
+ *       ||                                                          | |   |
+ *       ||                                                          | |   |
+ *       ||                                                          | |   |
+ *       ||                                                          |_|   |
+ *       ||                                                            |___|
+ * ||    ||                                                              +
+ * ||||--||                                                              |
+ * ||||--||--------------------------------------------------------------+
+ * ||
+ *
+ * History of Force Computers
+ *---------------------------
+ *
+ * Misc links about Force Computes and this board:
+ *------------------------------------------------
+ * http://bitsavers.trailing-edge.com/pdf/forceComputers/
+ *
+ * Description(s)
+ * -------------
+ * CPU-20 has the following feature set
+ *
+ * Address Map
+ * --------------------------------------------------------------------------
+ *  Range                   Decscription
+ * --------------------------------------------------------------------------
+ * 00000000-0xxFFFFF        Shared DRAM D8-D32
+ * 0yy00000-FAFFFFFF        VME A32 D8-D32     yy=xx+1
+ * FB000000-FBFEFFFF        VME A24 D8-D32
+ * FBFF0000-FBFFFFFF        VME A16 D8-D32
+ * FC000000-FCFEFFFF        VME A24 D8-D16
+ * FCFF0000-FCFFFFFF        VME A16 D8-D16
+ *  .... TBC
+ * --------------------------------------------------------------------------
+ *
+ * PIT #1 hardware wiring
+ * ----------------------------------------------------------
+ * PA0-PA3  TBC
+ * PA4-PA7
+ * H1-H4
+ * PB0-PB2
+ * PB3-PB4
+ * PB5
+ * PB6-PB7
+ * PC0,PC1
+ * PC4,PC7
+ * PC2
+ * PC3
+ * PC5
+ * PC6
+ *
+ * PIT #2 hardware setup wiring
+ * ----------------------------------------------------------
+ * PA0-PA7  TBC
+ * H1-H4
+ * PB0-PB2
+ * PB3-PB7
+ * PC0-PC1
+ * PC2
+ * PC3
+ * PC4
+ * PC5
+ * PC6
+ * PC7
+ *
+ *---------------------------------------------------------------------------
+ *  TODO:
+ *  - Find accurate documentation and adjust memory map
+ *  - Add layouts and system description(s)
+ *  - Write & add 68561 UART
+ *  - Write & add VME device
+ *  - Write & add 68153 BIM
+ *  - Add 68230 PIT
+ *  - Add variants of boards in the CPU-20 and CPU-21 family
+ *  - Add FGA, DUSCC devices and CPU-22 variants
+ *
+ ****************************************************************************/
+
+#include "emu.h"
+#include "cpu/m68000/m68000.h"
+#include "bus/rs232/rs232.h"
+#include "machine/clock.h"
+
+#define LOG_GENERAL 0x01
+#define LOG_SETUP   0x02
+#define LOG_PRINTF  0x04
+
+#define VERBOSE 0 // (LOG_PRINTF | LOG_SETUP  | LOG_GENERAL)
+
+#define LOGMASK(mask, ...)   do { if (VERBOSE & mask) logerror(__VA_ARGS__); } while (0)
+#define LOGLEVEL(mask, level, ...) do { if ((VERBOSE & mask) >= level) logerror(__VA_ARGS__); } while (0)
+
+#define LOG(...)      LOGMASK(LOG_GENERAL, __VA_ARGS__)
+#define LOGSETUP(...) LOGMASK(LOG_SETUP,   __VA_ARGS__)
+
+#if VERBOSE & LOG_PRINTF
+#define logerror printf
+#endif
+
+#ifdef _MSC_VER
+#define FUNCNAME __func__
+#else
+#define FUNCNAME __PRETTY_FUNCTION__
+#endif
+
+class cpu20_state : public driver_device
+{
+public:
+cpu20_state(const machine_config &mconfig, device_type type, const char *tag)
+		: driver_device (mconfig, type, tag)
+		, m_maincpu (*this, "maincpu")
+	{
+	}
+	DECLARE_READ32_MEMBER (bootvect_r);
+	DECLARE_WRITE32_MEMBER (bootvect_w);
+	virtual void machine_start () override;
+	virtual void machine_reset () override;
+
+private:
+	required_device<m68000_base_device> m_maincpu;
+	// Pointer to System ROMs needed by bootvect_r and masking RAM buffer for post reset accesses
+	uint32_t  *m_sysrom;
+	uint32_t  m_sysram[2];
+};
+
+static ADDRESS_MAP_START (cpu20_mem, AS_PROGRAM, 32, cpu20_state)
+	ADDRESS_MAP_UNMAP_HIGH
+	AM_RANGE (0x00000000, 0x00000007) AM_ROM AM_READ  (bootvect_r)   /* ROM mirror just during reset */
+	AM_RANGE (0x00000000, 0x00000007) AM_RAM AM_WRITE (bootvect_w)   /* After first write we act as RAM */
+	AM_RANGE (0x00000008, 0x003fffff) AM_RAM /* RAM  installed in machine start */
+	AM_RANGE (0xff040000, 0xff04ffff) AM_RAM /* RAM  installed in machine start */
+	AM_RANGE (0xff000000, 0xff00ffff) AM_ROM AM_REGION("roms", 0x0000)
+ADDRESS_MAP_END
+
+/* Input ports */
+static INPUT_PORTS_START (cpu20)
+INPUT_PORTS_END
+
+/* Start it up */
+void cpu20_state::machine_start ()
+{
+	LOGSETUP("%s\n", FUNCNAME);
+
+	save_pointer (NAME (m_sysrom), sizeof(m_sysrom));
+	save_pointer (NAME (m_sysram), sizeof(m_sysram));
+
+	/* Setup pointer to bootvector in ROM for bootvector handler bootvect_r */
+	m_sysrom = (uint32_t*)(memregion ("roms")->base());
+}
+
+void cpu20_state::machine_reset ()
+{
+	LOGSETUP("%s\n", FUNCNAME);
+
+	/* Reset pointer to bootvector in ROM for bootvector handler bootvect_r */
+	if (m_sysrom == &m_sysram[0]) /* Condition needed because memory map is not setup first time */
+		m_sysrom = (uint32_t*)(memregion ("roms")->base());
+}
+
+#if 0
+/*                                                                              setup board ID */
+DRIVER_INIT_MEMBER( cpu20_state, cpu20x )      { LOGSETUP("%s\n", FUNCNAME); m_board_id = 0x50; }
+DRIVER_INIT_MEMBER( cpu20_state, cpu20xa )     { LOGSETUP("%s\n", FUNCNAME); m_board_id = 0x50; }
+DRIVER_INIT_MEMBER( cpu20_state, cpu20za )     { LOGSETUP("%s\n", FUNCNAME); m_board_id = 0x50; }
+DRIVER_INIT_MEMBER( cpu20_state, cpu20zbe )    { LOGSETUP("%s\n", FUNCNAME); m_board_id = 0x50; }
+DRIVER_INIT_MEMBER( cpu20_state, cpu20be8 )    { LOGSETUP("%s\n", FUNCNAME); m_board_id = 0x50; }
+DRIVER_INIT_MEMBER( cpu20_state, cpu20be16 )   { LOGSETUP("%s\n", FUNCNAME); m_board_id = 0x50; }
+DRIVER_INIT_MEMBER( cpu20_state, cpu20lite4 )  { LOGSETUP("%s\n", FUNCNAME); m_board_id = 0x50; }
+DRIVER_INIT_MEMBER( cpu20_state, cpu20lite8 )  { LOGSETUP("%s\n", FUNCNAME); m_board_id = 0x50; }
+DRIVER_INIT_MEMBER( cpu20_state, cpu33 )       { LOGSETUP("%s\n", FUNCNAME); m_board_id = 0x68; } // 0x60 skips FGA prompt
+#endif
+
+/* Boot vector handler, the PCB hardwires the first 8 bytes from 0xff800000 to 0x0 at reset*/
+READ32_MEMBER (cpu20_state::bootvect_r){
+	LOG("%s\n", FUNCNAME);
+	return m_sysrom[offset];
+}
+
+WRITE32_MEMBER (cpu20_state::bootvect_w){
+	LOG("%s\n", FUNCNAME);
+	m_sysram[offset % sizeof(m_sysram)] &= ~mem_mask;
+	m_sysram[offset % sizeof(m_sysram)] |= (data & mem_mask);
+	m_sysrom = &m_sysram[0]; // redirect all upcomming accesses to masking RAM until reset.
+}
+
+#if 0
+void cpu20_state::update_irq_to_maincpu()
+{
+	LOGINT(("%s()\n", FUNCNAME);
+	LOGINT((" - fga_irq_level: %02x\n", fga_irq_level));
+	LOGINT((" - fga_irq_state: %02x\n", fga_irq_state));
+	switch (fga_irq_level & 0x07)
+	{
+	case 1: m_maincpu->set_input_line(M68K_IRQ_1, fga_irq_state); break;
+	case 2: m_maincpu->set_input_line(M68K_IRQ_2, fga_irq_state); break;
+	case 3: m_maincpu->set_input_line(M68K_IRQ_3, fga_irq_state); break;
+	case 4: m_maincpu->set_input_line(M68K_IRQ_4, fga_irq_state); break;
+	case 5: m_maincpu->set_input_line(M68K_IRQ_5, fga_irq_state); break;
+	case 6: m_maincpu->set_input_line(M68K_IRQ_6, fga_irq_state); break;
+	case 7: m_maincpu->set_input_line(M68K_IRQ_7, fga_irq_state); break;
+	default: logerror("Programmatic error in %s, please report\n", FUNCNAME);
+	}
+}
+#endif
+
+/*
+ * Machine configuration
+ */
+static MACHINE_CONFIG_START (cpu20, cpu20_state)
+	/* basic machine hardware */
+	MCFG_CPU_ADD ("maincpu", M68020, XTAL_16MHz) /* Crytstal not verified */
+	MCFG_CPU_PROGRAM_MAP (cpu20_mem)
+MACHINE_CONFIG_END
+
+/* ROM definitions */
+ROM_START (fccpu20) /* This is an original rom dump */
+	ROM_REGION32_BE(0x10000, "roms", 0)
+// Boots with Board ID set to: 0x36 (FGA002 BOOT on terminal P4, "Wait until harddisk is up to speed " on terminal P1)
+	ROM_LOAD32_BYTE("L.BIN",  0x000002, 0x4000, CRC (174ab801) SHA1 (0d7b8ed29d5fdd4bd2073005008120c5f20128dd))
+	ROM_LOAD32_BYTE("LL.BIN", 0x000003, 0x4000, CRC (9fd9e3e4) SHA1 (e5a7c87021e6be412dd5a8166d9f62b681169eda))
+	ROM_LOAD32_BYTE("U.BIN",  0x000001, 0x4000, CRC (d1afe4c0) SHA1 (b5baf9798d73632f7bb843cbc4b306c8c03f4296))
+	ROM_LOAD32_BYTE("UU.BIN", 0x000000, 0x4000, CRC (b54d623b) SHA1 (49b272184a04570b09004de71fae0ed0d1bf5929))
+ROM_END
+
+/*
+ * System ROM information
+ *
+ * xxxxxxx bootprom version xxx is released mmm dd, yyyy, coprighted by FORCE Computers Gmbh
+ */
+/* Driver */
+/*    YEAR  NAME          PARENT  COMPAT   MACHINE         INPUT     CLASS          INIT         COMPANY                   FULLNAME                FLAGS */
+COMP (1986, fccpu20,      0,       0,      cpu20,          cpu20,    driver_device,      0,      "Force Computers Gmbh",   "SYS68K/CPU-20",        MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW | MACHINE_TYPE_COMPUTER )
diff --git a/src/mame/drivers/fccpu30.cpp b/src/mame/drivers/fccpu30.cpp
index ffdab96..f07e9e0 100644
--- a/src/mame/drivers/fccpu30.cpp
+++ b/src/mame/drivers/fccpu30.cpp
@@ -699,7 +699,7 @@ static MACHINE_CONFIG_START (cpu30, cpu30_state)
 	MCFG_PIT68230_PB_OUTPUT_CB(WRITE8(cpu30_state, flop_dmac_w))
 	MCFG_PIT68230_PC_INPUT_CB(READ8(cpu30_state, pit1c_r))
 	MCFG_PIT68230_PC_OUTPUT_CB(WRITE8(cpu30_state, pit1c_w))
-// MCFG_PIT68230_OUT_INT_CB(DEVWRITELINE("fga002", fga002_device, lirq2_w)) // Interrupts not yet supported by 68230
+//  MCFG_PIT68230_TIMER_IRQ_CB(DEVWRITELINE("fga002", fga002_device, lirq2_w)) // The timer interrupt seems to silence the terminal interrupt, needs invectigation
 
 	MCFG_DEVICE_ADD ("pit2", PIT68230, XTAL_16MHz / 2) // Th PIT clock is not verified on schema but reversed from behaviour
 	MCFG_PIT68230_PB_INPUT_CB(READ8(cpu30_state, board_mem_id_rd))
@@ -707,7 +707,7 @@ static MACHINE_CONFIG_START (cpu30, cpu30_state)
 	MCFG_PIT68230_PA_OUTPUT_CB(WRITE8(cpu30_state, pit2a_w))
 	MCFG_PIT68230_PC_INPUT_CB(READ8(cpu30_state, pit2c_r))
 	MCFG_PIT68230_PC_OUTPUT_CB(WRITE8(cpu30_state, pit2c_w))
-// MCFG_PIT68230_OUT_INT_CB(DEVWRITELINE("fga002", fga002_device, lirq3_w)) // Interrupts not yet supported by 68230
+//  MCFG_PIT68230_TIMER_IRQ_CB(DEVWRITELINE("fga002", fga002_device, lirq3_w)) // The timer interrupt seems to silence the terminal interrupt, needs invectigation
 
 	/* FGA-002, Force Gate Array */
 	MCFG_FGA002_ADD("fga002", 0)
diff --git a/src/mame/drivers/fcombat.cpp b/src/mame/drivers/fcombat.cpp
index b711d06..74b0ebb 100644
--- a/src/mame/drivers/fcombat.cpp
+++ b/src/mame/drivers/fcombat.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 
 /* Field Combat (c)1985 Jaleco
diff --git a/src/mame/drivers/fcrash.cpp b/src/mame/drivers/fcrash.cpp
index d24b4aa..3f74761 100644
--- a/src/mame/drivers/fcrash.cpp
+++ b/src/mame/drivers/fcrash.cpp
@@ -491,7 +491,8 @@ void cps_state::fcrash_render_sprites( screen_device &screen, bitmap_ind16 &bitm
 	int num_sprites = m_gfxdecode->gfx(2)->elements();
 	int last_sprite_offset = 0x1ffc;
 	uint16_t *sprite_ram = m_gfxram;
-	uint16_t tileno,flipx,flipy,colour,xpos,ypos;
+	uint16_t tileno,colour,xpos,ypos;
+	bool flipx, flipy;
 
 	/* if we have separate sprite ram, use it */
 	if (m_bootleg_sprite_ram) sprite_ram = m_bootleg_sprite_ram.get();
@@ -509,13 +510,16 @@ void cps_state::fcrash_render_sprites( screen_device &screen, bitmap_ind16 &bitm
 			if (tileno >= num_sprites) continue; /* don't render anything outside our tiles */
 			xpos   = sprite_ram[base + pos + 2] & 0x1ff;
 			ypos   = sprite_ram[base + pos - 1] & 0x1ff;
-			flipx  = sprite_ram[base + pos + 1] & 0x20;
-			flipy  = sprite_ram[base + pos + 1] & 0x40;
+			flipx  = BIT(sprite_ram[base + pos + 1], 5);
+			flipy  = BIT(sprite_ram[base + pos + 1], 6);
 			colour = sprite_ram[base + pos + 1] & 0x1f;
 			ypos   = 256 - ypos - 16;
 			xpos   = xpos + m_sprite_x_offset + 49;
 
-			m_gfxdecode->gfx(2)->prio_transpen(bitmap,cliprect, tileno, colour, flipx, flipy, xpos, ypos, screen.priority(), 0x02, 15);
+			if (flip_screen())
+				m_gfxdecode->gfx(2)->prio_transpen(bitmap, cliprect, tileno, colour, !flipx, !flipy, 512-16-xpos, 256-16-ypos, screen.priority(), 2, 15);
+			else
+				m_gfxdecode->gfx(2)->prio_transpen(bitmap, cliprect, tileno, colour, flipx, flipy, xpos, ypos, screen.priority(), 2, 15);
 		}
 	}
 }
diff --git a/src/mame/drivers/fidel6502.cpp b/src/mame/drivers/fidel6502.cpp
index 266788f..08b725b 100644
--- a/src/mame/drivers/fidel6502.cpp
+++ b/src/mame/drivers/fidel6502.cpp
@@ -1801,6 +1801,13 @@ static MACHINE_CONFIG_START( fdes2100d, fidel6502_state )
 	MCFG_SOUND_ROUTE_EX(0, "dac", 1.0, DAC_VREF_POS_INPUT)
 MACHINE_CONFIG_END
 
+static MACHINE_CONFIG_DERIVED( fdes2000d, fdes2100d )
+
+	/* basic machine hardware */
+	MCFG_CPU_REPLACE("maincpu", R65C02, XTAL_3MHz) // R65C02P3
+	MCFG_CPU_PROGRAM_MAP(fdesdis_map)
+MACHINE_CONFIG_END
+
 static MACHINE_CONFIG_START( chesster, fidel6502_state )
 
 	/* basic machine hardware */
@@ -2129,12 +2136,12 @@ ROM_START( fscc12 )
 ROM_END
 
 
-ROM_START( fexcel ) // PCB label 510.1117A02
+ROM_START( fexcel ) // model 6080(B), PCB label 510.1117A02
 	ROM_REGION( 0x10000, "maincpu", 0 )
 	ROM_LOAD("101-1080a01.ic5", 0x8000, 0x8000, CRC(846f8e40) SHA1(4e1d5b08d5ff3422192b54fa82cb3f505a69a971) ) // same as fexcelv
 ROM_END
 
-#define rom_fexceld rom_fexcelb /* model 6093, PCB label 510.1117A02 */
+#define rom_fexceld rom_fexcel /* model 6093, PCB label 510.1117A02 */
 
 ROM_START( fexcelv ) // model 6092, PCB label 510.1117A02, sound PCB 510.1117A01
 	ROM_REGION( 0x10000, "maincpu", 0 )
@@ -2144,12 +2151,12 @@ ROM_START( fexcelv ) // model 6092, PCB label 510.1117A02, sound PCB 510.1117A01
 	ROM_LOAD("101-1081a01.ic2", 0x0000, 0x8000, CRC(c8ae1607) SHA1(6491ce6be60ed77f3dd931c0ca17616f13af943e) ) // PCB2, M27256
 ROM_END
 
-ROM_START( fexcela ) // PCB label 510-1099A01
+ROM_START( fexcela ) // model 6080, PCB label 510-1099A01(manuf.1985) or 510-1099B01(manuf.1986)
 	ROM_REGION( 0x10000, "maincpu", 0 )
 	ROM_LOAD("101-1072a01.ic5", 0xc000, 0x4000, CRC(212b006d) SHA1(242ff851b0841cbec66bbada6a730da021010e2c) )
 ROM_END
 
-ROM_START( fexcelb ) // PCB label 510-1099A01
+ROM_START( fexcelb ) // model EP12, PCB label 510-1099A01
 	ROM_REGION( 0x10000, "maincpu", 0 )
 	ROM_LOAD("101-1072b01.ic5", 0xc000, 0x4000, CRC(fd2f6064) SHA1(f84bb98bdb9565a04891eb6820597d7aecc90c21) ) // RCA
 ROM_END
@@ -2173,6 +2180,13 @@ ROM_START( fdes2100d ) // model 6106, PCB label 510.1130A01. The 'rev B' dump ca
 	ROM_LOAD("bk3_white.ic10", 0x0000, 0x8000, CRC(3857cc35) SHA1(f073dafb9fd885c7ddb7fbff10e3653f343ef1c6) ) // WSI 27C256L-12
 ROM_END
 
+ROM_START( fdes2000d ) // model 6105, PCB label 510.1130A01
+	ROM_REGION( 0x10000, "maincpu", 0 )
+	ROM_LOAD("27c256.ic9", 0x8000, 0x8000, CRC(b136d1a1) SHA1(8438790a62f45284ff33a0255c5c89f526726d3e) ) // 27C256, no label
+
+	ROM_REGION( 0x8000, "user1", ROMREGION_ERASEFF ) // no rom in ic10
+ROM_END
+
 
 ROM_START( chesster ) // model 6120, PCB label 510.1141C01
 	ROM_REGION( 0x10000, "maincpu", 0 )
@@ -2226,10 +2240,11 @@ CONS( 1987, fexcelv,    fexcel,   0,      fexcelv,   fexcelv,   driver_device, 0
 CONS( 1987, fexceld,    fexcel,   0,      fexceld,   fexcelb,   driver_device, 0, "Fidelity Electronics", "Excel Display", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK )
 CONS( 1985, fexcela,    fexcel,   0,      fexcel,    fexcel,    driver_device, 0, "Fidelity Electronics", "The Excellence (model EP12)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK ) // 1st version of The Excellence
 CONS( 1985, fexcelb,    fexcel,   0,      fexcel,    fexcel,    driver_device, 0, "Fidelity Electronics", "The Excellence (model 6080)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK )
-CONS( 1986, fexcelp,    0,        0,      fexcelp,   fexcel,    driver_device, 0, "Fidelity Electronics", "The Par Excellence", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK )
+CONS( 1986, fexcelp,    fexcel,   0,      fexcelp,   fexcel,    driver_device, 0, "Fidelity Electronics", "The Par Excellence", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK )
 
 CONS( 1989, fdes2000,   0,        0,      fdes2000,  fdes,      driver_device, 0, "Fidelity Electronics", "Designer 2000", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK ) // Excellence series hardware
 
 CONS( 1988, fdes2100d,  0,        0,      fdes2100d, fdesdis,   fidel6502_state, fdesdis, "Fidelity Electronics", "Designer 2100 Display (rev. B)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK )
+CONS( 1988, fdes2000d,  fdes2100d,0,      fdes2000d, fdesdis,   fidel6502_state, fdesdis, "Fidelity Electronics", "Designer 2000 Display", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK )
 
 CONS( 1990, chesster,   0,        0,      chesster,  chesster,  fidel6502_state, chesster, "Fidelity Electronics", "Chesster Challenger", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK )
diff --git a/src/mame/drivers/freekick.cpp b/src/mame/drivers/freekick.cpp
index b94db7b..b8c2d32 100644
--- a/src/mame/drivers/freekick.cpp
+++ b/src/mame/drivers/freekick.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina,David Haywood
 /***************************************************************************
 
diff --git a/src/mame/drivers/fromance.cpp b/src/mame/drivers/fromance.cpp
index f135a18..4d77ccd 100644
--- a/src/mame/drivers/fromance.cpp
+++ b/src/mame/drivers/fromance.cpp
@@ -37,6 +37,13 @@ Memo:
 
 - 2player's input is not supported.
 
+- Identify CRT Controller and fix layer misalignment in nekkyoku.
+
+- nekkyoku: soft reset enables flip screen without any real reason.
+
+- nekkyoku writes to a VRAM mirror for showing the OL gal, I guess ROM mirroring
+  is the same for all empty slots for this HW.
+
 - Communication between MAIN CPU and SUB CPU can be wrong.
 
 Notes:
@@ -727,7 +734,7 @@ static INPUT_PORTS_START( daiyogen )
 	PORT_DIPSETTING(    0x01, DEF_STR( Off ) )
 	PORT_DIPNAME( 0x06, 0x00, "Player Initial Score" )  PORT_DIPLOCATION("SW1:!2,!3")
 	PORT_DIPSETTING(    0x00, "1,000" )
-		PORT_DIPSETTING(    0x04, "1,500" )
+	PORT_DIPSETTING(    0x04, "1,500" )
 	PORT_DIPSETTING(    0x02, "2,000" )
 	PORT_DIPSETTING(    0x06, "3,000" )
 	PORT_DIPNAME( 0x18, 0x00, "Computer Difficulty" )   PORT_DIPLOCATION("SW1:!4,!5")
@@ -880,7 +887,6 @@ MACHINE_START_MEMBER(fromance_state,fromance)
 
 	membank("bank1")->configure_entries(0, 0x100, &ROM[0x10000], 0x4000);
 
-
 	save_item(NAME(m_directionflag));
 	save_item(NAME(m_commanddata));
 	save_item(NAME(m_portselect));
@@ -1071,7 +1077,14 @@ ROM_START( nekkyoku )
 	ROM_LOAD( "ic8a.bin",    0x000000, 0x080000, CRC(599790d8) SHA1(4e4ade1a89d6cb93b0808867883d70c4c7ed78dd) )
 	ROM_LOAD( "ic9a.bin",    0x080000, 0x040000, CRC(78c1906f) SHA1(54459e0120ec58a962d3f4a1287e68d2fbb28be9) )
 	ROM_LOAD( "5-ic10a.bin", 0x0c0000, 0x008000, CRC(2e78515f) SHA1(397985c082ffc0df07cd44d54e4fef909c30a4f1) )
-	ROM_FILL(                0x0c8000, 0x038000, 0xff )
+	// 'D' OL girl is displayed via one of these mirrors
+	ROM_RELOAD(              0x0c8000, 0x008000 )
+	ROM_RELOAD(              0x0d0000, 0x008000 )
+	ROM_RELOAD(              0x0d8000, 0x008000 )
+	ROM_RELOAD(              0x0e0000, 0x008000 )
+	ROM_RELOAD(              0x0e8000, 0x008000 )
+	ROM_RELOAD(              0x0f0000, 0x008000 )
+	ROM_RELOAD(              0x0f8000, 0x008000 )
 	ROM_FILL(                0x100000, 0x100000, 0xff )
 ROM_END
 
@@ -1253,7 +1266,7 @@ ROM_END
  *
  *************************************/
 
-GAME( 1988, nekkyoku,  0,       nekkyoku, nekkyoku, driver_device, 0, ROT0, "Video System Co.", "Rettou Juudan Nekkyoku Janshi - Higashi Nippon Hen (Japan)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
+GAME( 1988, nekkyoku,  0,       nekkyoku, nekkyoku, driver_device, 0, ROT0, "Video System Co.", "Rettou Juudan Nekkyoku Janshi - Higashi Nippon Hen (Japan)", MACHINE_SUPPORTS_SAVE )
 GAME( 1988, idolmj,    0,       idolmj,   idolmj, driver_device,   0, ROT0, "System Service", "Idol-Mahjong Housoukyoku (Japan)", MACHINE_SUPPORTS_SAVE )
 GAME( 1989, mjnatsu,   0,       fromance, mjnatsu, driver_device,  0, ROT0, "Video System Co.", "Mahjong Natsu Monogatari (Japan)", MACHINE_SUPPORTS_SAVE )
 GAME( 1989, natsuiro,  mjnatsu, fromance, mjnatsu, driver_device,  0, ROT0, "Video System Co.", "Natsuiro Mahjong (Japan)", MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/drivers/gaiden.cpp b/src/mame/drivers/gaiden.cpp
index 48b4d12..838d879 100644
--- a/src/mame/drivers/gaiden.cpp
+++ b/src/mame/drivers/gaiden.cpp
@@ -774,7 +774,7 @@ static MACHINE_CONFIG_START( shadoww, gaiden_state )
 	MCFG_TECMO_MIXER_SHIFTS(10,9,4)
 	MCFG_TECMO_MIXER_BLENDCOLS(   0x0400 + 0x300, 0x0400 + 0x200, 0x0400 + 0x100, 0x0400 + 0x000 )
 	MCFG_TECMO_MIXER_REGULARCOLS( 0x0000 + 0x300, 0x0000 + 0x200, 0x0000 + 0x100, 0x0000 + 0x000 )
-	MCFG_TECMO_MIXER_BLENDSOUCE( 0x0800 + 0x000, 0x0800 + 0x200)
+	MCFG_TECMO_MIXER_BLENDSOURCE( 0x0800 + 0x000, 0x0800 + 0x200)
 	MCFG_TECMO_MIXER_REVSPRITETILE
 	MCFG_TECMO_MIXER_BGPEN(0x000 + 0x200)
 
diff --git a/src/mame/drivers/galaxian.cpp b/src/mame/drivers/galaxian.cpp
index d71a07b..742be3e 100644
--- a/src/mame/drivers/galaxian.cpp
+++ b/src/mame/drivers/galaxian.cpp
@@ -8142,6 +8142,25 @@ ROM_START( uniwarsa )
 	ROM_LOAD( "kareteco.clr",  0x0000, 0x0020, CRC(6a0c7d87) SHA1(140335d85c67c75b65689d4e76d29863c209cf32) )
 ROM_END
 
+ROM_START( mltiwars )
+	ROM_REGION( 0x4000, "maincpu", 0 )
+	ROM_LOAD( "g1.bin",  0x0000, 0x0800, CRC(d975af10) SHA1(a2e2a36a75db8fd09441308b08b6ae073c68b8cf) )
+	ROM_LOAD( "g2.bin",  0x0800, 0x0800, CRC(b2ed14c3) SHA1(7668df11f64b8e296eedfee53437777dc53a56d5) )
+	ROM_LOAD( "g3.bin",  0x1000, 0x0800, CRC(945f4160) SHA1(5fbe879f51e14c4c7ae551e5b3089f8e148770a4) )
+	ROM_LOAD( "g4.bin",  0x1800, 0x0800, CRC(ef28ec00) SHA1(f57fc2fd38b0ef7ee206f70f161a5f6963de1e94) )
+	ROM_LOAD( "g5.bin",  0x2000, 0x0800, CRC(855ab0dd) SHA1(50aae48726f092d1815f5534e041673bad2b50ac) )
+	ROM_LOAD( "g6.bin",  0x2800, 0x0800, CRC(d915a389) SHA1(0e2ff6eec9453856a1276889946b463cfae58eba) )
+	ROM_LOAD( "g7.bin",  0x3000, 0x0800, CRC(c9245346) SHA1(239bad3fe64eaab2dfc3febd06d1124103a10504) )
+	ROM_LOAD( "g8.bin",  0x3800, 0x0800, CRC(797d45c7) SHA1(76fb8b45fcce3622c59c04af32cfa001ef7bf71d) )
+
+	ROM_REGION( 0x2000, "gfx1", 0 )
+	ROM_LOAD( "g14.bin", 0x0000, 0x1000, CRC(227f9e8e) SHA1(6316ad92053b22df0d9621738507883c55003d3b) )
+	ROM_LOAD( "g15.bin", 0x1000, 0x1000, CRC(3f8b6a24) SHA1(00b8434c0de32af301137f9370f991e5e7192980) )
+
+	ROM_REGION( 0x0020, "proms", 0 )
+	ROM_LOAD( "prom.bin", 0x0000, 0x0020, CRC(6a0c7d87) SHA1(140335d85c67c75b65689d4e76d29863c209cf32) )
+ROM_END
+
 ROM_START( spacempr )
 	ROM_REGION( 0x4000, "maincpu", 0 )
 	ROM_LOAD( "uw01",   0x0000, 0x0800, CRC(7c64fb92) SHA1(69f0923870cb8cbb7ae7a2a056c67a1da9b5588d) )
@@ -11621,6 +11640,7 @@ GAME( 19??, piscesb,     pisces,   galaxian,   piscesb,    galaxian_state, pisce
 GAME( 19??, omni,        pisces,   galaxian,   piscesb,    galaxian_state, pisces,     ROT90,  "bootleg", "Omni", MACHINE_SUPPORTS_SAVE )
 GAME( 1980, uniwars,     0,        galaxian,   superg,     galaxian_state, pisces,     ROT90,  "Irem", "UniWar S", MACHINE_SUPPORTS_SAVE )
 GAME( 1980, uniwarsa,    uniwars,  galaxian,   superg,     galaxian_state, pisces,     ROT90,  "bootleg (Karateco)", "UniWar S (bootleg)", MACHINE_SUPPORTS_SAVE )
+GAME( 1980, mltiwars,    uniwars,  galaxian,   superg,     galaxian_state, pisces,     ROT90,  "bootleg (Gayton Games)", "Multi Wars (bootleg of UniWar S)", MACHINE_SUPPORTS_SAVE )
 GAME( 1980, gteikoku,    uniwars,  galaxian,   superg,     galaxian_state, pisces,     ROT90,  "Irem", "Gingateikoku No Gyakushu", MACHINE_SUPPORTS_SAVE )
 GAME( 1980, gteikokb,    uniwars,  galaxian,   gteikokb,   galaxian_state, pisces,     ROT270, "bootleg", "Gingateikoku No Gyakushu (bootleg set 1)", MACHINE_SUPPORTS_SAVE )
 GAME( 1980, gteikob2,    uniwars,  galaxian,   gteikob2,   galaxian_state, pisces,     ROT90,  "bootleg", "Gingateikoku No Gyakushu (bootleg set 2)", MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/drivers/gammagic.cpp b/src/mame/drivers/gammagic.cpp
index 6fb0385..33bffb2 100644
--- a/src/mame/drivers/gammagic.cpp
+++ b/src/mame/drivers/gammagic.cpp
@@ -31,7 +31,6 @@ Additional CD-ROM games: "99 Bottles of Beer"
 
 #include "emu.h"
 #include "cpu/i386/i386.h"
-#include "machine/cr589.h"
 //#include "machine/i82371sb.h"
 //#include "machine/i82439tx.h"
 #include "machine/lpci.h"
diff --git a/src/mame/drivers/gcpinbal.cpp b/src/mame/drivers/gcpinbal.cpp
index 8cdf862..a495ec7 100644
--- a/src/mame/drivers/gcpinbal.cpp
+++ b/src/mame/drivers/gcpinbal.cpp
@@ -2,8 +2,13 @@
 // copyright-holders:David Graves, R. Belmont
 /***************************************************************************
 
-Grand Cross Pinball
-===================
+Excellent System's ES-9209B Hardware
+
+Games supported:
+
+   Grand Cross Pinball
+   Power Flipper Pinball Shooting
+
 
 Made from Raine source
 
@@ -23,6 +28,7 @@ TODO
  - Hook up ES-8712
  - Sort out the IOC commands for the M6585 & ES-8712
  - Is SW3 actually used?
+ - Missing row scroll (column scroll?)
 
 BGMs (controlled by OKI MSM6585 sound chip)
   MSM6585: is an upgraded MSM5205 voice synth IC.
@@ -71,6 +77,9 @@ Custom: EXCELLENT SYSTEM ES-9208 347102 (QFP160)
 
 * Denotes unpopulated components
 
+NOTE: Mask roms from Power Flipper Pinball Shooting have not been dumped, but assumed to
+      be the same data.
+
 ***************************************************************************/
 
 #include "emu.h"
@@ -500,6 +509,30 @@ MACHINE_CONFIG_END
                                   DRIVERS
 ***************************************************************************/
 
+ROM_START( pwrflip ) /* Updated version of Grand Cross Pinball or semi-sequel? */
+	ROM_REGION( 0x200000, "maincpu", 0 )  /* 512k for 68000 program */
+	ROM_LOAD16_WORD_SWAP( "p.f_1.33.u43",  0x000000, 0x80000, CRC(d760c987) SHA1(9200604377542193afc866c84733f2d3b5aa1c80) ) /* hand written labels on genuine EXCELLENT labels */
+	ROM_FILL            ( 0x80000,  0x080000, 0x00 ) /* unpopulated 27C4096 socket at U44 */
+	ROM_LOAD16_WORD_SWAP( "p.f.u45",       0x100000, 0x80000, CRC(6ad1a457) SHA1(8746c38efa05e3318e9b1a371470d149803fb6bb) )
+	ROM_LOAD16_WORD_SWAP( "p.f.u46",       0x180000, 0x80000, CRC(e0f3a1b4) SHA1(761dddf374a92c1a1e4a211ead215d5be461a082) )
+
+	ROM_REGION( 0x200000, "gfx1", 0 )  /* BG0 (16 x 16) */
+	ROM_LOAD( "u1",      0x000000, 0x100000, CRC(afa459bb) SHA1(7a7c64bcb80d71b8cf3fdd3209ef109997b6417c) ) /* 23C8000 MASK ROMs */
+	ROM_LOAD( "u6",      0x100000, 0x100000, CRC(c3f024e5) SHA1(d197e2b715b154fc64ff9a61f8c6df111d6fd446) )
+
+	ROM_REGION( 0x020000, "gfx2", 0 )  /* FG0 (8 x 8) */
+	ROM_LOAD( "p.f.u10",   0x000000, 0x020000, CRC(50e34549) SHA1(ca1808513ff3feb8bcd34d9aafd7b374e4244732) )
+
+	ROM_REGION( 0x200000, "gfx3", 0 )  /* Sprites (16 x 16) */
+	ROM_LOAD( "u13",     0x000000, 0x200000, CRC(62f3952f) SHA1(7dc9ccb753d46b6aaa791bcbf6e18e6d872f6b79) ) /* 23C16000 MASK ROM */
+
+	ROM_REGION( 0x080000, "oki", 0 )   /* M6295 acc to Raine */
+	ROM_LOAD( "u55",   0x000000, 0x080000, CRC(b3063351) SHA1(825e63e8a824d67d235178897528e5b0b41e4485) ) /* OKI M534001B MASK ROM */
+
+	ROM_REGION( 0x200000, "msm", 0 )   /* M6585 acc to Raine but should be for ES-8712??? */
+	ROM_LOAD( "u56",   0x000000, 0x200000, CRC(092b2c0f) SHA1(2ec1904e473ddddb50dbeaa0b561642064d45336) ) /* 23C16000 MASK ROM */
+ROM_END
+
 ROM_START( gcpinbal )
 	ROM_REGION( 0x200000, "maincpu", 0 )  /* 512k for 68000 program */
 	ROM_LOAD16_WORD_SWAP( "2_excellent.u43",  0x000000, 0x80000, CRC(d174bd7f) SHA1(0e6c17265e1400de941e3e2ca3be835aaaff6695) ) /* Red line across label */
@@ -525,5 +558,5 @@ ROM_START( gcpinbal )
 ROM_END
 
 
-
-GAME( 1994, gcpinbal, 0, gcpinbal, gcpinbal, driver_device, 0, ROT270, "Excellent System", "Grand Cross", MACHINE_IMPERFECT_SOUND | MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE )
+GAME( 1994, pwrflip,  0, gcpinbal, gcpinbal, driver_device, 0, ROT270, "Excellent System", "Power Flipper Pinball Shooting v1.33", MACHINE_IMPERFECT_SOUND | MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE )
+GAME( 1994, gcpinbal, 0, gcpinbal, gcpinbal, driver_device, 0, ROT270, "Excellent System", "Grand Cross v1.02F", MACHINE_IMPERFECT_SOUND | MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/drivers/genpc.cpp b/src/mame/drivers/genpc.cpp
index 2b8bf33..af1adf7 100644
--- a/src/mame/drivers/genpc.cpp
+++ b/src/mame/drivers/genpc.cpp
@@ -8,9 +8,6 @@
 
 ***************************************************************************/
 
-
-
-
 #include "emu.h"
 #include "machine/genpc.h"
 #include "cpu/nec/nec.h"
@@ -30,12 +27,7 @@ public:
 
 static ADDRESS_MAP_START( pc8_map, AS_PROGRAM, 8, genpc_state )
 	ADDRESS_MAP_UNMAP_HIGH
-	AM_RANGE(0xf0000, 0xfffff) AM_ROM AM_REGION("bios", 0)
-ADDRESS_MAP_END
-
-static ADDRESS_MAP_START( pc16_map, AS_PROGRAM, 16, genpc_state )
-	ADDRESS_MAP_UNMAP_HIGH
-	AM_RANGE(0xf0000, 0xfffff) AM_ROM AM_REGION("bios", 0)
+	AM_RANGE(0xfe000, 0xfffff) AM_ROM AM_REGION("bios", 0)
 ADDRESS_MAP_END
 
 static ADDRESS_MAP_START(pc8_io, AS_IO, 8, genpc_state )
@@ -43,12 +35,6 @@ static ADDRESS_MAP_START(pc8_io, AS_IO, 8, genpc_state )
 	AM_RANGE(0x0000, 0x00ff) AM_DEVICE("mb", ibm5160_mb_device, map)
 ADDRESS_MAP_END
 
-static ADDRESS_MAP_START(pc16_io, AS_IO, 16, genpc_state )
-	ADDRESS_MAP_UNMAP_HIGH
-	AM_RANGE(0x0000, 0x00ff) AM_DEVICE8("mb", ibm5160_mb_device, map, 0xffff)
-ADDRESS_MAP_END
-
-
 static DEVICE_INPUT_DEFAULTS_START(cga)
 	DEVICE_INPUT_DEFAULTS("DSW0",0x30, 0x20)
 DEVICE_INPUT_DEFAULTS_END
@@ -59,7 +45,7 @@ DEVICE_INPUT_DEFAULTS_END
 
 static MACHINE_CONFIG_START( pcmda, genpc_state )
 	/* basic machine hardware */
-	MCFG_CPU_ADD("maincpu", V20, 4772720)
+	MCFG_CPU_ADD("maincpu", I8088, 4772720)
 	MCFG_CPU_PROGRAM_MAP(pc8_map)
 	MCFG_CPU_IO_MAP(pc8_io)
 	MCFG_CPU_IRQ_ACKNOWLEDGE_DEVICE("mb:pic8259", pic8259_device, inta_cb)
@@ -74,7 +60,7 @@ static MACHINE_CONFIG_START( pcmda, genpc_state )
 	MCFG_ISA8_SLOT_ADD("mb:isa", "isa6", pc_isa8_cards, nullptr, false)
 
 	/* keyboard */
-	MCFG_PC_KBDC_SLOT_ADD("mb:pc_kbdc", "kbd", pc_xt_keyboards, STR_KBD_KEYTRONIC_PC3270)
+	MCFG_PC_KBDC_SLOT_ADD("mb:pc_kbdc", "kbd", pc_xt_keyboards, STR_KBD_IBM_PC_XT_83)
 
 	/* internal ram */
 	MCFG_RAM_ADD(RAM_TAG)
@@ -93,10 +79,6 @@ MACHINE_CONFIG_END
 
 
 static MACHINE_CONFIG_DERIVED( pccga, pcmda )
-	MCFG_CPU_REPLACE("maincpu",  I8086, 4772720)
-	MCFG_CPU_PROGRAM_MAP(pc16_map)
-	MCFG_CPU_IO_MAP(pc16_io)
-	MCFG_CPU_IRQ_ACKNOWLEDGE_DEVICE("mb:pic8259", pic8259_device, inta_cb)
 	MCFG_DEVICE_MODIFY("mb")
 	MCFG_DEVICE_INPUT_DEFAULTS(cga)
 	MCFG_DEVICE_MODIFY("isa1")
@@ -112,64 +94,56 @@ static MACHINE_CONFIG_DERIVED( pcega, pccga )
 MACHINE_CONFIG_END
 
 
-static MACHINE_CONFIG_DERIVED( xtvga, pcega )
+static MACHINE_CONFIG_DERIVED( pcvga, pcega )
 	MCFG_DEVICE_MODIFY("isa1")
-	MCFG_DEVICE_SLOT_INTERFACE(pc_isa8_cards, "svga_et4k", false)
+	MCFG_DEVICE_SLOT_INTERFACE(pc_isa8_cards, "vga", false)
 MACHINE_CONFIG_END
 
-
-ROM_START( pcmda )
-	ROM_REGION(0x10000,"bios", 0)
-	ROM_SYSTEM_BIOS(0, "anon", "XT Anonymous Generic Turbo BIOS")
-	ROMX_LOAD("pcxt.rom",    0xe000, 0x02000, CRC(031aafad) SHA1(a641b505bbac97b8775f91fe9b83d9afdf4d038f),ROM_BIOS(1))
-	ROM_SYSTEM_BIOS(1, "anon2007", "XT Anonymous Generic Turbo BIOS 2007")
-	ROMX_LOAD( "pcxt2007.bin", 0xe000, 0x2000, CRC(1d7bd86c) SHA1(33a500f599b4dad2fe6d7a5c3e89b13bd5dd2987),ROM_BIOS(2))
-	ROM_SYSTEM_BIOS(2, "ami", "XT AMI")
-	ROMX_LOAD( "ami.bin", 0xe000, 0x2000, CRC(b381eb22) SHA1(9735193de119270c946a17ed58c3ab9554e0852e),ROM_BIOS(3))
-	ROM_SYSTEM_BIOS(3, "award", "XT Award 2.05")
-	ROMX_LOAD( "award2.05.bin", 0xe000, 0x2000, CRC(5b3953e5) SHA1(4a36171aa8d993008187f39f732b9296401b7b6c),ROM_BIOS(4))
-	ROM_SYSTEM_BIOS(4, "dtk", "XT DTK Erso bios 2.42")
-	ROMX_LOAD( "dtk2.42.bin", 0xe000, 0x2000, CRC(3f2d2a76) SHA1(02fa057f2c22ab199a8d9795ab1ae570f2b13a36),ROM_BIOS(5))
-	ROM_SYSTEM_BIOS(5, "peter", "XT Peter Kohlman 3.75") // V20 Rom only
-	ROMX_LOAD( "peterv203.75.bin", 0xe000, 0x2000, CRC(b053a6a4) SHA1(f53218ad3d725f12d9149b22d8afcf6a8869a3bd),ROM_BIOS(6))
-	ROM_SYSTEM_BIOS(6, "pho227", "XT Phoenix Bios 2.27")
-	ROMX_LOAD( "phoenix2.27.bin", 0xe000, 0x2000, CRC(168ffef0) SHA1(69465db2f9246a614044d1f433d374506a13a07f),ROM_BIOS(7))
-	ROM_SYSTEM_BIOS(7, "pho251", "XT Phoenix Bios 2.51")
-	ROMX_LOAD( "phoenix2.51.bin", 0xe000, 0x2000, CRC(9b7e9c40) SHA1(c948a8d3d715e469105c6e2acd8b46ec274b25a8),ROM_BIOS(8))
-	ROM_SYSTEM_BIOS(8, "turbo", "XT Turbo Bios 3.10")
-	ROMX_LOAD( "turbo3.10.bin", 0xe000, 0x2000, CRC(8aaca1e3) SHA1(9c03da16713e08c0112a04c8bdfa394e7341c1fc),ROM_BIOS(9))
+ROM_START(pc)
+	ROM_REGION(0x02000, "bios", 0)
+	ROM_SYSTEM_BIOS(0, "v30", "Turbo XT BIOS 3.0")
+	ROMX_LOAD("pcxtbios30.rom", 0x00000, 0x02000, CRC(4e1fd77a) SHA1(36873971c47b242db7edad7a0c1ea2f7f8d43b87),ROM_BIOS(1))
+	ROM_SYSTEM_BIOS(1, "v26", "Turbo XT BIOS 2.6")
+	ROMX_LOAD("pcxtbios26.rom", 0x00000, 0x02000, CRC(a7505acd) SHA1(1fdd80b09feed0ac59401fd6d8dae6250cb56054),ROM_BIOS(2))
+	ROM_SYSTEM_BIOS(2, "v25", "Turbo XT BIOS 2.5")
+	ROMX_LOAD("pcxtbios25.rom", 0x00000, 0x02000, CRC(1ab22db6) SHA1(e681acec93c79b08ec06fd26d3be4cccd28f7a45),ROM_BIOS(3))
+	ROM_SYSTEM_BIOS(3, "v24", "Turbo XT BIOS 2.4")
+	ROMX_LOAD("pcxtbios24.rom", 0x00000, 0x02000, CRC(80e3c43f) SHA1(3f623cf12f3375aa0fa59da84b5137b9fc86c0ce),ROM_BIOS(4))
+	ROM_SYSTEM_BIOS(4, "v23", "Turbo XT BIOS 2.3")
+	ROMX_LOAD("pcxtbios23.rom", 0x00000, 0x02000, CRC(f397485a) SHA1(777826be2feadb3a8cf7a28ed2245dddef8e1d23),ROM_BIOS(5))
+	ROM_SYSTEM_BIOS(5, "v22", "Turbo XT BIOS 2.2")
+	ROMX_LOAD("pcxtbios22.rom", 0x00000, 0x02000, CRC(00967678) SHA1(2dd7f6c8236673e471dd456be009dcc43e28a09f),ROM_BIOS(6))
+	ROM_SYSTEM_BIOS(6, "v21", "Turbo XT BIOS 2.1")
+	ROMX_LOAD("pcxtbios21.rom", 0x00000, 0x02000, CRC(017f8f61) SHA1(d9696ba16b56685eb51612eddf1a75364acae7af),ROM_BIOS(7))
+	ROM_SYSTEM_BIOS(7, "v20", "Turbo XT BIOS 2.0")
+	ROMX_LOAD("xtbios2.rom",    0x00000, 0x02000, CRC(1d7bd86c) SHA1(33a500f599b4dad2fe6d7a5c3e89b13bd5dd2987),ROM_BIOS(8))
+	ROM_SYSTEM_BIOS(8, "v10", "XT Anonymous Generic Turbo BIOS")
+	ROMX_LOAD("pcxt.rom",       0x00000, 0x02000, CRC(031aafad) SHA1(a641b505bbac97b8775f91fe9b83d9afdf4d038f),ROM_BIOS(9))
+
+	// List of bioses to go to separate drivers
+	ROM_SYSTEM_BIOS(9, "ami", "XT AMI")
+	ROMX_LOAD( "ami.bin", 0x00000, 0x2000, CRC(b381eb22) SHA1(9735193de119270c946a17ed58c3ab9554e0852e),ROM_BIOS(10))
+	ROM_SYSTEM_BIOS(10, "award", "XT Award 2.05")
+	ROMX_LOAD( "award2.05.bin", 0x00000, 0x2000, CRC(5b3953e5) SHA1(4a36171aa8d993008187f39f732b9296401b7b6c),ROM_BIOS(11))
+	ROM_SYSTEM_BIOS(11, "dtk", "XT DTK Erso bios 2.42")
+	ROMX_LOAD( "dtk2.42.bin", 0x00000, 0x2000, CRC(3f2d2a76) SHA1(02fa057f2c22ab199a8d9795ab1ae570f2b13a36),ROM_BIOS(12))
+	ROM_SYSTEM_BIOS(12, "peter", "XT Peter Kohlman 3.75") // V20 Rom only
+	ROMX_LOAD( "peterv203.75.bin", 0x00000, 0x2000, CRC(b053a6a4) SHA1(f53218ad3d725f12d9149b22d8afcf6a8869a3bd),ROM_BIOS(13))
+	ROM_SYSTEM_BIOS(13, "pho227", "XT Phoenix Bios 2.27")
+	ROMX_LOAD( "phoenix2.27.bin", 0x00000, 0x2000, CRC(168ffef0) SHA1(69465db2f9246a614044d1f433d374506a13a07f),ROM_BIOS(14))
+	ROM_SYSTEM_BIOS(14, "pho251", "XT Phoenix Bios 2.51")
+	ROMX_LOAD( "phoenix2.51.bin", 0x00000, 0x2000, CRC(9b7e9c40) SHA1(c948a8d3d715e469105c6e2acd8b46ec274b25a8),ROM_BIOS(15))
+	ROM_SYSTEM_BIOS(15, "turbo", "XT Turbo Bios 3.10")
+	ROMX_LOAD( "turbo3.10.bin", 0x00000, 0x2000, CRC(8aaca1e3) SHA1(9c03da16713e08c0112a04c8bdfa394e7341c1fc),ROM_BIOS(16))
 ROM_END
 
-#define rom_pcherc    rom_pcmda
-
-#define rom_pcega    rom_pcmda
-
-ROM_START( pc )
-	ROM_REGION(0x10000,"bios", 0)
-	ROM_SYSTEM_BIOS(0, "anon", "XT Anonymous Generic Turbo BIOS")
-	ROMX_LOAD("pcxt.rom",    0xe000, 0x02000, CRC(031aafad) SHA1(a641b505bbac97b8775f91fe9b83d9afdf4d038f),ROM_BIOS(1))
-	ROM_SYSTEM_BIOS(1, "anon2007", "XT Anonymous Generic Turbo BIOS 2007")
-	ROMX_LOAD( "pcxt2007.bin", 0xe000, 0x2000, CRC(1d7bd86c) SHA1(33a500f599b4dad2fe6d7a5c3e89b13bd5dd2987),ROM_BIOS(2))
-	ROM_SYSTEM_BIOS(2, "ami", "XT AMI")
-	ROMX_LOAD( "ami.bin", 0xe000, 0x2000, CRC(b381eb22) SHA1(9735193de119270c946a17ed58c3ab9554e0852e),ROM_BIOS(3))
-	ROM_SYSTEM_BIOS(3, "award", "XT Award 2.05")
-	ROMX_LOAD( "award2.05.bin", 0xe000, 0x2000, CRC(5b3953e5) SHA1(4a36171aa8d993008187f39f732b9296401b7b6c),ROM_BIOS(4))
-	ROM_SYSTEM_BIOS(4, "dtk", "XT DTK Erso bios 2.42")
-	ROMX_LOAD( "dtk2.42.bin", 0xe000, 0x2000, CRC(3f2d2a76) SHA1(02fa057f2c22ab199a8d9795ab1ae570f2b13a36),ROM_BIOS(5))
-	ROM_SYSTEM_BIOS(5, "peter", "XT Peter Kohlman 3.75")
-	ROMX_LOAD( "peterv203.75.bin", 0xe000, 0x2000, CRC(b053a6a4) SHA1(f53218ad3d725f12d9149b22d8afcf6a8869a3bd),ROM_BIOS(6))
-	ROM_SYSTEM_BIOS(6, "pho227", "XT Phoenix Bios 2.27")
-	ROMX_LOAD( "phoenix2.27.bin", 0xe000, 0x2000, CRC(168ffef0) SHA1(69465db2f9246a614044d1f433d374506a13a07f),ROM_BIOS(7))
-	ROM_SYSTEM_BIOS(7, "pho251", "XT Phoenix Bios 2.51")
-	ROMX_LOAD( "phoenix2.51.bin", 0xe000, 0x2000, CRC(9b7e9c40) SHA1(c948a8d3d715e469105c6e2acd8b46ec274b25a8),ROM_BIOS(8))
-	ROM_SYSTEM_BIOS(8, "turbo", "XT Turbo Bios 3.10")
-	ROMX_LOAD( "turbo3.10.bin", 0xe000, 0x2000, CRC(8aaca1e3) SHA1(9c03da16713e08c0112a04c8bdfa394e7341c1fc),ROM_BIOS(9))
-	/* IBM 1501981(CGA) and 1501985(MDA) Character rom */
-	ROM_REGION(0x2000,"gfx1", 0)
-	ROM_LOAD("5788005.u33", 0x00000, 0x2000, CRC(0bf56d70) SHA1(c2a8b10808bf51a3c123ba3eb1e9dd608231916f)) /* "AMI 8412PI // 5788005 // (C) IBM CORP. 1981 // KOREA" */
-ROM_END
+#define rom_pcmda    rom_pc
+
+#define rom_pcherc   rom_pc
+
+#define rom_pcega    rom_pc
 
-#define rom_xtvga    rom_pcmda
+#define rom_pcvga    rom_pc
 
 /***************************************************************************
 
@@ -182,4 +156,4 @@ COMP(  1987,    pc,         ibm5150,    0,      pccga,      0,     driver_device
 COMP(  1987,    pcega,      ibm5150,    0,      pcega,      0,     driver_device,       0,          "<generic>",  "PC (EGA)" , 0)
 COMP ( 1987,    pcmda,      ibm5150,    0,      pcmda,      0,     driver_device,       0,          "<generic>",  "PC (MDA)" , 0)
 COMP ( 1987,    pcherc,     ibm5150,    0,      pcherc,     0,     driver_device,       0,          "<generic>",  "PC (Hercules)" , 0)
-COMP ( 1987,    xtvga,      ibm5150,    0,      xtvga,      0,     driver_device,       0,          "<generic>",  "PC (VGA)" , MACHINE_NOT_WORKING)
+COMP ( 1987,    pcvga,      ibm5150,    0,      pcvga,      0,     driver_device,       0,          "<generic>",  "PC (VGA)" , 0)
diff --git a/src/mame/drivers/ginganin.cpp b/src/mame/drivers/ginganin.cpp
index 2346803..1e5c2fe 100644
--- a/src/mame/drivers/ginganin.cpp
+++ b/src/mame/drivers/ginganin.cpp
@@ -250,8 +250,7 @@ static MACHINE_CONFIG_START( ginganin, ginganin_state )
 	MCFG_CPU_PROGRAM_MAP(sound_map)
 
 
-	MCFG_DEVICE_ADD("6840ptm", PTM6840, 0)
-	MCFG_PTM6840_INTERNAL_CLOCK(SOUND_CLOCK/2)
+	MCFG_DEVICE_ADD("6840ptm", PTM6840, SOUND_CLOCK/2)
 	MCFG_PTM6840_EXTERNAL_CLOCKS(0, 0, 0)
 	MCFG_PTM6840_OUT0_CB(WRITELINE(ginganin_state, ptm_irq))
 
diff --git a/src/mame/drivers/gkigt.cpp b/src/mame/drivers/gkigt.cpp
index 2d4f400..9ea6627 100644
--- a/src/mame/drivers/gkigt.cpp
+++ b/src/mame/drivers/gkigt.cpp
@@ -78,8 +78,9 @@ PCB board that connects to 044 boards via J6 & J7
     Adds the abillity to use legacy 038 EPROM based software
     or 039 EPROM + SIMM software
 
-
-
+More chips (from eBay auction):
+    2x Phillips / NXT 28C94 quad UART (8 serial channels total)
+    ADV476 256 color RAMDAC
 */
 
 #include "emu.h"
@@ -90,9 +91,12 @@ class igt_gameking_state : public driver_device
 {
 public:
 	igt_gameking_state(const machine_config &mconfig, device_type type, const char *tag)
-		: driver_device(mconfig, type, tag)
+		: driver_device(mconfig, type, tag),
+		m_palette(*this, "palette")
 	{ }
 
+	required_device<palette_device> m_palette;
+
 	virtual void video_start() override;
 	uint32_t screen_update_igt_gameking(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
 
@@ -101,7 +105,7 @@ public:
 
 	DECLARE_READ32_MEMBER(igt_gk_28010008_r)
 	{
-		return rand();
+		return rand();  // don't quite understand this one
 	};
 
 	DECLARE_READ32_MEMBER(igt_gk_28030000_r)
@@ -109,13 +113,57 @@ public:
 		return rand();
 	};
 
+	DECLARE_READ32_MEMBER(uart_status_r);
+	DECLARE_WRITE32_MEMBER(uart_w);
+	DECLARE_WRITE32_MEMBER(clut_w);
+	DECLARE_WRITE32_MEMBER(clut_mask_w);
 
+private:
+	int m_offset, m_r, m_g, m_b, m_state;
+	bool m_bToggle;
+	u8 m_clut_mask;
 };
 
 static INPUT_PORTS_START( igt_gameking )
 INPUT_PORTS_END
 
+WRITE32_MEMBER(igt_gameking_state::clut_w)
+{
+	if (mem_mask == 0x000000ff)
+	{
+		m_offset = data & 0xff;
+		m_state = 0;
+	}
+	else if (mem_mask == 0x00ff0000)
+	{
+		switch (m_state)
+		{
+			case 0: m_r = (data>>16) & 0xff; m_state++; break;
+			case 1: m_g = (data>>16) & 0xff; m_state++; break;
+			case 2:
+				m_b = (data>>16) & 0xff;
+				//printf("CLUT: color %d = R %d G %d B %d\n", m_offset, m_r, m_g, m_b);
+				m_palette->set_pen_color(m_offset, m_r<<18 | m_g<<10 | m_b<<2);
+				m_state = 0;
+				break;
+		}
+	}
+}
 
+WRITE32_MEMBER(igt_gameking_state::clut_mask_w)
+{
+	m_clut_mask = data & 0xff;
+}
+
+READ32_MEMBER(igt_gameking_state::uart_status_r)
+{
+	return 0x00040000;
+}
+
+WRITE32_MEMBER(igt_gameking_state::uart_w)
+{
+	printf("%c", (data>>16) & 0x7f);
+}
 
 void igt_gameking_state::machine_start()
 {
@@ -123,6 +171,9 @@ void igt_gameking_state::machine_start()
 
 void igt_gameking_state::machine_reset()
 {
+	m_bToggle = false;
+	m_offset = m_state = m_r = m_g = m_b = 0;
+	m_clut_mask = 0xff;
 }
 
 void igt_gameking_state::video_start()
@@ -140,14 +191,22 @@ static ADDRESS_MAP_START( igt_gameking_mem, AS_PROGRAM, 32, igt_gameking_state )
 	AM_RANGE(0x00000000, 0x0007ffff) AM_ROM
 	AM_RANGE(0x08000000, 0x081fffff) AM_ROM AM_REGION("game", 0)
 
-	AM_RANGE(0x10000000, 0x1000001f) AM_RAM
-	AM_RANGE(0x10000020, 0x1000021f) AM_RAM // strange range to test, correct or CPU issue?
-	AM_RANGE(0x10000220, 0x1003ffff) AM_RAM
+	AM_RANGE(0x10000000, 0x10ffffff) AM_RAM
+
+	AM_RANGE(0x18000000, 0x181fffff) AM_RAM // igtsc writes from 18000000 to 1817ffff, ms3 all the way to 181fffff.
 
+	// 28010000-2801007f: first 28C94 QUART
 	AM_RANGE(0x28010008, 0x2801000b) AM_READ(igt_gk_28010008_r)
+	AM_RANGE(0x28010030, 0x28010033) AM_READ(uart_status_r) // channel D
+	AM_RANGE(0x28010034, 0x28010037) AM_WRITE(uart_w)       // channel D
+	// 28020000-2802007f: second 28C94 QUART
 	AM_RANGE(0x28030000, 0x28030003) AM_READ(igt_gk_28030000_r)
+	AM_RANGE(0x28040000, 0x2804ffff) AM_RAM
+	AM_RANGE(0x28050000, 0x28050003) AM_DEVREADWRITE8("ymz", ymz280b_device, read, write, 0x00ff00ff)
+	AM_RANGE(0x28060000, 0x28060003) AM_WRITE(clut_w)
+	AM_RANGE(0x28060004, 0x28060007) AM_WRITE(clut_mask_w)
 
-
+	AM_RANGE(0xa1000000, 0xa1011fff) AM_RAM // used by gkkey for restart IAC
 
 ADDRESS_MAP_END
 
@@ -198,6 +257,25 @@ static MACHINE_CONFIG_START( igt_gameking, igt_gameking_state )
 
 MACHINE_CONFIG_END
 
+ROM_START( ms3 )
+	ROM_REGION( 0x80000, "maincpu", 0 )
+	ROM_LOAD( "3b5060ax.u8",  0x000000, 0x080000, CRC(aff8d874) SHA1(1cb972759ee12c944a1cfdbe68848c9b2e64a4d3) )
+
+	ROM_REGION32_LE( 0x200000, "game", 0 )
+	ROM_LOAD16_BYTE( "ea5006ax.u21", 0x000000, 0x080000, CRC(9109b2e2) SHA1(daa1f01315caf6e08c3cf8b0e4925c86d2cd8dc3) )
+	ROM_LOAD16_BYTE( "ea5006ax.u5",  0x000001, 0x080000, CRC(66c33cf6) SHA1(600f75ab112348f43b38cafd6f871559372f2807) )
+
+	ROM_REGION( 0x100000, "cg", 0 )
+	ROM_LOAD16_BYTE( "1g5032ax.u48", 0x000000, 0x040000, CRC(aba6002f) SHA1(2ed51aa8bbc1e703cd63f633d745dfa4fa7f3dd0) )
+	ROM_LOAD16_BYTE( "1g5032ax.u47", 0x000001, 0x040000, CRC(605a71ec) SHA1(13fe64c611c0903a7b79d8680de3ac81f3226a67) )
+
+	ROM_REGION( 0x200000, "plx", 0 )
+	ROM_LOAD16_BYTE( "1g5032ax.u20", 0x000000, 0x100000, CRC(517e7478) SHA1(316a8e48ad6502f9508b06f900555d53ef40b464) )
+	ROM_LOAD16_BYTE( "1g5032ax.u4",  0x000001, 0x100000, CRC(e67c878f) SHA1(b03f8d28924351e96bb9f24d32f0e4a40a51910c) )
+
+	ROM_REGION( 0x200000, "snd", 0 )
+	ROM_LOAD( "1h5053xx.u6",  0x000000, 0x080000, CRC(6735c65a) SHA1(198cacec5441aa615c0de63a0b4e47265636bcee) )
+ROM_END
 
 ROM_START( ms72c )
 	ROM_REGION( 0x80000, "maincpu", 0 )
@@ -389,7 +467,7 @@ ROM_START( gkkey )
 	ROM_REGION( 0x200000, "snd", ROMREGION_ERASEFF )
 ROM_END
 
-
+GAME( 1994, ms3,      0,            igt_gameking, igt_gameking, driver_device,  0, ROT0, "IGT", "Multistar 3", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
 GAME( 1994, ms72c,    0,            igt_gameking, igt_gameking, driver_device,  0, ROT0, "IGT", "Multistar 7 2c", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
 GAME( 2003, gkigt4,   0,            igt_gameking, igt_gameking, driver_device,  0, ROT0, "IGT", "Game King (v4.x)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
 GAME( 2003, gkigt4ms, gkigt4,       igt_gameking, igt_gameking, driver_device,  0, ROT0, "IGT", "Game King (v4.x, MS)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
diff --git a/src/mame/drivers/gottlieb.cpp b/src/mame/drivers/gottlieb.cpp
index 032cdc9..ece7524 100644
--- a/src/mame/drivers/gottlieb.cpp
+++ b/src/mame/drivers/gottlieb.cpp
@@ -1822,38 +1822,6 @@ MACHINE_CONFIG_END
  *
  *************************************/
 
-#if USE_FAKE_VOTRAX
-
-static MACHINE_CONFIG_DERIVED( reactor, gottlieb1 )
-
-	/* basic machine hardware */
-	MCFG_CPU_MODIFY("maincpu")
-	MCFG_CPU_PROGRAM_MAP(reactor_map)
-
-	MCFG_DEVICE_REMOVE("nvram")
-
-	/* sound hardware */
-	MCFG_FRAGMENT_ADD(reactor_samples)
-MACHINE_CONFIG_END
-
-
-static MACHINE_CONFIG_DERIVED( qbert, gottlieb1 )
-
-	/* sound hardware */
-	MCFG_FRAGMENT_ADD(qbert_knocker)
-	MCFG_FRAGMENT_ADD(qbert_samples)
-MACHINE_CONFIG_END
-
-
-static MACHINE_CONFIG_DERIVED( tylz, gottlieb1 )
-
-	/* sound hardware */
-	MCFG_FRAGMENT_ADD(qbert_samples)
-MACHINE_CONFIG_END
-
-
-#else
-
 
 static MACHINE_CONFIG_DERIVED( gottlieb1_votrax, gottlieb_core )
 	MCFG_SOUND_ADD("r1sound", GOTTLIEB_SOUND_REV1_WITH_VOTRAX, 0)
@@ -1882,9 +1850,6 @@ static MACHINE_CONFIG_DERIVED( tylz, gottlieb1_votrax )
 MACHINE_CONFIG_END
 
 
-#endif
-
-
 static MACHINE_CONFIG_DERIVED( screwloo, gottlieb2 )
 
 	MCFG_VIDEO_START_OVERRIDE(gottlieb_state,screwloo)
diff --git a/src/mame/drivers/guab.cpp b/src/mame/drivers/guab.cpp
index cbe9184..3fae6e6 100644
--- a/src/mame/drivers/guab.cpp
+++ b/src/mame/drivers/guab.cpp
@@ -1,5 +1,5 @@
-// license:BSD-3-Clause
-// copyright-holders:Philip Bennett
+// license: BSD-3-Clause
+// copyright-holders: Philip Bennett, Dirk Best
 /***************************************************************************
 
     JPM Give us a Break hardware
@@ -22,44 +22,38 @@
         count gets updated in the code. Each game requires a unique
         security PAL - maybe this is related? I'm poking the coin values
         directly into RAM for now.
+        * Game hangs when you try to 'collect' cash
         * Verify WD FDC type
+        * Are IRQs 1 or 2 connected to something?
+        * Hook up ACIA properly (IRQ 4)
+        * Hook up watchdog NMI
+        * Verify clocks
+        * Use real video timings
+        * Create layouts
+
+    Notes:
+        * Toggle both 'Back door' and 'Key switch' to enter test mode
+        * Video hardware seems to match JPM System 5
 
 ***************************************************************************/
 
 #include "emu.h"
 #include "cpu/m68000/m68000.h"
 #include "machine/6840ptm.h"
+#include "machine/i8255.h"
+#include "machine/6850acia.h"
 #include "video/tms34061.h"
+#include "video/ef9369.h"
 #include "sound/sn76496.h"
 #include "machine/wd_fdc.h"
 #include "formats/guab_dsk.h"
 #include "softlist.h"
+#include "guab.lh"
 
-/*************************************
- *
- *  Defines
- *
- *************************************/
-
-
-enum int_levels
-{
-	INT_UNKNOWN1     = 1,
-	INT_UNKNOWN2     = 2,
-	INT_6840PTM      = 3,
-	INT_6850ACIA     = 4,
-	INT_TMS34061     = 5,
-	INT_FLOPPYCTRL   = 6,
-	INT_WATCHDOG_INT = 7
-};
-
-
-struct ef9369
-{
-	uint32_t addr;
-	uint16_t clut[16];    /* 13-bits - a marking bit and a 444 color */
-};
 
+//**************************************************************************
+//  TYPE DEFINITIONS
+//**************************************************************************
 
 class guab_state : public driver_device
 {
@@ -71,19 +65,29 @@ public:
 		m_sn(*this, "snsnd"),
 		m_fdc(*this, "fdc"),
 		m_floppy(*this, "fdc:0"),
-		m_palette(*this, "palette") { }
-
-	DECLARE_WRITE_LINE_MEMBER(generate_tms34061_interrupt);
-	DECLARE_WRITE16_MEMBER(guab_tms34061_w);
-	DECLARE_READ16_MEMBER(guab_tms34061_r);
-	DECLARE_WRITE16_MEMBER(ef9369_w);
-	DECLARE_READ16_MEMBER(ef9369_r);
-	DECLARE_READ16_MEMBER(io_r);
-	DECLARE_WRITE16_MEMBER(io_w);
-	DECLARE_INPUT_CHANGED_MEMBER(coin_inserted);
-	DECLARE_WRITE_LINE_MEMBER(ptm_irq);
+		m_palette(*this, "palette"),
+		m_sound_buffer(0), m_sound_latch(false)
+	{ }
+
+	EF9369_COLOR_UPDATE(ef9369_color_update);
+	DECLARE_WRITE16_MEMBER(tms34061_w);
+	DECLARE_READ16_MEMBER(tms34061_r);
 	uint32_t screen_update_guab(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
 
+	DECLARE_WRITE8_MEMBER(output1_w);
+	DECLARE_WRITE8_MEMBER(output2_w);
+	DECLARE_WRITE8_MEMBER(output3_w);
+	DECLARE_WRITE8_MEMBER(output4_w);
+	DECLARE_WRITE8_MEMBER(output5_w);
+	DECLARE_WRITE8_MEMBER(output6_w);
+	DECLARE_READ8_MEMBER(sn76489_ready_r);
+	DECLARE_WRITE8_MEMBER(sn76489_buffer_w);
+	DECLARE_WRITE8_MEMBER(system_w);
+	DECLARE_READ8_MEMBER(watchdog_r);
+	DECLARE_WRITE8_MEMBER(watchdog_w);
+
+	DECLARE_INPUT_CHANGED_MEMBER(coin_inserted);
+
 	DECLARE_FLOPPY_FORMATS(floppy_formats);
 
 protected:
@@ -97,37 +101,117 @@ private:
 	required_device<floppy_connector> m_floppy;
 	required_device<palette_device> m_palette;
 
-	struct ef9369 m_pal;
+	uint8_t m_sound_buffer;
+	bool m_sound_latch;
 };
 
 
-/*************************************
- *
- *  6840 PTM
- *
- *************************************/
+//**************************************************************************
+//  ADDRESS MAPS
+//**************************************************************************
 
-WRITE_LINE_MEMBER(guab_state::ptm_irq)
-{
-	m_maincpu->set_input_line(INT_6840PTM, state);
-}
+static ADDRESS_MAP_START( guab_map, AS_PROGRAM, 16, guab_state )
+	AM_RANGE(0x000000, 0x00ffff) AM_ROM
+	AM_RANGE(0x040000, 0x04ffff) AM_ROM AM_REGION("maincpu", 0x10000)
+	AM_RANGE(0x0c0000, 0x0c0007) AM_DEVREADWRITE8("i8255_1", i8255_device, read, write, 0x00ff)
+	AM_RANGE(0x0c0020, 0x0c0027) AM_DEVREADWRITE8("i8255_2", i8255_device, read, write, 0x00ff)
+	AM_RANGE(0x0c0040, 0x0c0047) AM_DEVREADWRITE8("i8255_3", i8255_device, read, write, 0x00ff)
+	AM_RANGE(0x0c0060, 0x0c0067) AM_DEVREADWRITE8("i8255_4", i8255_device, read, write, 0x00ff)
+	AM_RANGE(0x0c0080, 0x0c0081) AM_DEVREADWRITE8("acia6850_1", acia6850_device, status_r, control_w, 0x00ff)
+	AM_RANGE(0x0c0082, 0x0c0083) AM_DEVREADWRITE8("acia6850_1", acia6850_device, data_r, data_w, 0x00ff)
+	AM_RANGE(0x0c00a0, 0x0c00a1) AM_DEVREADWRITE8("acia6850_2", acia6850_device, status_r, control_w, 0x00ff)
+	AM_RANGE(0x0c00a2, 0x0c00a3) AM_DEVREADWRITE8("acia6850_2", acia6850_device, data_r, data_w, 0x00ff)
+	AM_RANGE(0x0c00c0, 0x0c00cf) AM_DEVREADWRITE8("6840ptm", ptm6840_device, read, write, 0x00ff)
+	AM_RANGE(0x0c00e0, 0x0c00e7) AM_DEVREADWRITE8("fdc", wd1773_t, read, write, 0x00ff)
+	AM_RANGE(0x080000, 0x080fff) AM_RAM
+	AM_RANGE(0x100000, 0x100001) AM_DEVREADWRITE8("ef9369", ef9369_device, data_r, data_w, 0x00ff)
+	AM_RANGE(0x100002, 0x100003) AM_DEVWRITE8("ef9369", ef9369_device, address_w, 0x00ff)
+	AM_RANGE(0x800000, 0xb0ffff) AM_READWRITE(tms34061_r, tms34061_w)
+	AM_RANGE(0xb10000, 0xb1ffff) AM_RAM
+	AM_RANGE(0xb80000, 0xb8ffff) AM_RAM
+	AM_RANGE(0xb90000, 0xb9ffff) AM_RAM
+ADDRESS_MAP_END
+
+
+//**************************************************************************
+//  INPUTS
+//**************************************************************************
+
+static INPUT_PORTS_START( guab )
+	PORT_START("IN0")
+	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN3 )   PORT_NAME("50p") PORT_CHANGED_MEMBER(DEVICE_SELF, guab_state,coin_inserted, (void *)50)
+	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN4 )   PORT_NAME("100p") PORT_CHANGED_MEMBER(DEVICE_SELF, guab_state,coin_inserted, (void *)100)
+	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_NAME("Back door") PORT_CODE(KEYCODE_R) PORT_TOGGLE
+	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_NAME("Cash door") PORT_CODE(KEYCODE_T) PORT_TOGGLE
+	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_NAME("Key switch") PORT_CODE(KEYCODE_Y) PORT_TOGGLE
+	PORT_BIT( 0x20, IP_ACTIVE_HIGH,IPT_UNUSED )  PORT_NAME("50p level")
+	PORT_BIT( 0x40, IP_ACTIVE_HIGH,IPT_UNUSED )  PORT_NAME("100p level")
+	PORT_BIT( 0x80, IP_ACTIVE_HIGH,IPT_UNUSED )
+
+	PORT_START("IN1")
+	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
+	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
+	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_START1 )
+	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
+	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED )
+	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
+	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("A")
+	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("B")
+
+	PORT_START("IN2")
+	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("Select")
+	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
+	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
+	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
+	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("C")
+	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("D")
+	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN1 )   PORT_NAME("10p") PORT_CHANGED_MEMBER(DEVICE_SELF, guab_state,coin_inserted, (void *)10)
+	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_COIN2 )   PORT_NAME("20p") PORT_CHANGED_MEMBER(DEVICE_SELF, guab_state,coin_inserted, (void *)20)
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( tenup )
+	PORT_START("IN0")
+	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN3 )   PORT_NAME("50p") PORT_CHANGED_MEMBER(DEVICE_SELF, guab_state,coin_inserted, (void *)50)
+	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN4 )   PORT_NAME("100p") PORT_CHANGED_MEMBER(DEVICE_SELF, guab_state,coin_inserted, (void *)100)
+	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_NAME("Back door") PORT_CODE(KEYCODE_R) PORT_TOGGLE
+	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_NAME("Cash door") PORT_CODE(KEYCODE_T) PORT_TOGGLE
+	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_NAME("Key switch") PORT_CODE(KEYCODE_Y) PORT_TOGGLE
+	PORT_BIT( 0x20, IP_ACTIVE_HIGH,IPT_UNUSED )  PORT_NAME("10p level")
+	PORT_BIT( 0x40, IP_ACTIVE_HIGH,IPT_UNUSED )  PORT_NAME("100p level")
+	PORT_BIT( 0x80, IP_ACTIVE_HIGH,IPT_UNUSED )
+
+	PORT_START("IN1")
+	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
+	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
+	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_START1 )
+	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
+	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED )
+	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
+	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
+	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("Pass")
+
+	PORT_START("IN2")
+	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("Collect")
+	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
+	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
+	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("A")
+	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("B")
+	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("C")
+	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN1 )   PORT_NAME("10p")  PORT_CHANGED_MEMBER(DEVICE_SELF, guab_state,coin_inserted, (void *)10)
+	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_COIN2 )   PORT_NAME("20p")  PORT_CHANGED_MEMBER(DEVICE_SELF, guab_state,coin_inserted, (void *)20)
+INPUT_PORTS_END
 
-/*************************************
- *
- *  Video hardware
- *
- *************************************/
 
-/*****************
- * TMS34061 CRTC
- *****************/
+//**************************************************************************
+//  VIDEO EMULATION
+//**************************************************************************
 
-WRITE_LINE_MEMBER(guab_state::generate_tms34061_interrupt)
+EF9369_COLOR_UPDATE( guab_state::ef9369_color_update )
 {
-	m_maincpu->set_input_line(INT_TMS34061, state);
+	m_palette->set_pen_color(entry, pal4bit(ca), pal4bit(cb), pal4bit(cc));
 }
 
-WRITE16_MEMBER(guab_state::guab_tms34061_w)
+WRITE16_MEMBER( guab_state::tms34061_w )
 {
 	int func = (offset >> 19) & 3;
 	int row = (offset >> 7) & 0xff;
@@ -145,8 +229,7 @@ WRITE16_MEMBER(guab_state::guab_tms34061_w)
 		m_tms34061->write(space, col | 1, row, func, data & 0xff);
 }
 
-
-READ16_MEMBER(guab_state::guab_tms34061_r)
+READ16_MEMBER( guab_state::tms34061_r )
 {
 	uint16_t data = 0;
 	int func = (offset >> 19) & 3;
@@ -167,76 +250,8 @@ READ16_MEMBER(guab_state::guab_tms34061_r)
 	return data;
 }
 
-
-/****************************
- *  EF9369 color palette IC
- *  (16 colors from 4096)
- ****************************/
-
-/* Non-multiplexed mode */
-WRITE16_MEMBER(guab_state::ef9369_w)
-{
-	struct ef9369 &pal = m_pal;
-	data &= 0x00ff;
-
-	/* Address register */
-	if (offset & 1)
-	{
-		pal.addr = data & 0x1f;
-	}
-	/* Data register */
-	else
-	{
-		uint32_t entry = pal.addr >> 1;
-
-		if ((pal.addr & 1) == 0)
-		{
-			pal.clut[entry] &= ~0x00ff;
-			pal.clut[entry] |= data;
-		}
-		else
-		{
-			uint16_t col;
-
-			pal.clut[entry] &= ~0x1f00;
-			pal.clut[entry] |= (data & 0x1f) << 8;
-
-			/* Remove the marking bit */
-			col = pal.clut[entry] & 0xfff;
-
-			/* Update the MAME palette */
-			m_palette->set_pen_color(entry, pal4bit(col >> 0), pal4bit(col >> 4), pal4bit(col >> 8));
-		}
-
-			/* Address register auto-increment */
-		if (++pal.addr == 32)
-			pal.addr = 0;
-	}
-}
-
-READ16_MEMBER(guab_state::ef9369_r)
-{
-	struct ef9369 &pal = m_pal;
-	if ((offset & 1) == 0)
-	{
-		uint16_t col = pal.clut[pal.addr >> 1];
-
-		if ((pal.addr & 1) == 0)
-			return col & 0xff;
-		else
-			return col >> 8;
-	}
-	else
-	{
-		/* Address register is write only */
-		return 0xffff;
-	}
-}
-
 uint32_t guab_state::screen_update_guab(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
 {
-	int x, y;
-
 	m_tms34061->get_display_state();
 
 	/* If blanked, fill with black */
@@ -246,12 +261,12 @@ uint32_t guab_state::screen_update_guab(screen_device &screen, bitmap_ind16 &bit
 		return 0;
 	}
 
-	for (y = cliprect.min_y; y <= cliprect.max_y; ++y)
+	for (int y = cliprect.min_y; y <= cliprect.max_y; ++y)
 	{
 		uint8_t *src = &m_tms34061->m_display.vram[256 * y];
 		uint16_t *dest = &bitmap.pix16(y);
 
-		for (x = cliprect.min_x; x <= cliprect.max_x; x += 2)
+		for (int x = cliprect.min_x; x <= cliprect.max_x; x += 2)
 		{
 			uint8_t pen = src[x >> 1];
 
@@ -265,38 +280,53 @@ uint32_t guab_state::screen_update_guab(screen_device &screen, bitmap_ind16 &bit
 }
 
 
-/****************************************
- *
- *  Hardware inputs (coins, buttons etc)
- *
- ****************************************/
+//**************************************************************************
+//  MACHINE EMULATION
+//**************************************************************************
+
+void guab_state::machine_start()
+{
+	m_fdc->set_floppy(m_floppy->get_device());
+}
+
+READ8_MEMBER( guab_state::watchdog_r )
+{
+	// only read after writing the sequence below
+	return 0xff;
+}
 
-READ16_MEMBER(guab_state::io_r)
+WRITE8_MEMBER( guab_state::watchdog_w )
 {
-	static const char *const portnames[] = { "IN0", "IN1", "IN2" };
+	// watchdog?
+	// writes b 3 1 5 d a 2 0 4 0 8   b 3 1 5 d a 2 0 4 0 8
+	// then later toggles between 0 and f
+}
 
-	switch (offset)
+WRITE8_MEMBER( guab_state::system_w )
+{
+	// bit 0, sound latch
+	if (m_sound_latch != bool(BIT(data, 0)))
 	{
-		case 0x00:
-		case 0x01:
-		case 0x02:
-		{
-			return ioport(portnames[offset])->read();
-		}
-		case 0x30:
-		{
-			/* Whatever it is, bit 7 must be 0 */
-			return 0x7f;
-		}
-		default:
-		{
-			osd_printf_debug("Unknown IO R:0x%x\n", 0xc0000 + (offset * 2));
-			return 0;
-		}
+		// falling edge
+		if (!m_sound_latch)
+			m_sn->write(m_sound_buffer);
+
+		m_sound_latch = bool(BIT(data, 0));
 	}
+
+	// bit 3, floppy drive side select
+	m_floppy->get_device()->ss_w(BIT(data, 3));
+
+	// one of those bits will probably control the motor, we just let it run all the time for now
+	m_floppy->get_device()->mon_w(0);
 }
 
-INPUT_CHANGED_MEMBER(guab_state::coin_inserted)
+
+//**************************************************************************
+//  INPUTS/OUTPUTS
+//**************************************************************************
+
+INPUT_CHANGED_MEMBER( guab_state::coin_inserted )
 {
 	if (newval == 0)
 	{
@@ -309,183 +339,99 @@ INPUT_CHANGED_MEMBER(guab_state::coin_inserted)
 	}
 }
 
-/****************************************
- *
- *  Hardware outputs (lamps, meters etc)
- *
- ****************************************/
-
-WRITE16_MEMBER(guab_state::io_w)
+WRITE8_MEMBER( guab_state::output1_w )
 {
-	switch (offset)
-	{
-		case 0x10:
-		{
-			/* Outputs 0 - 7 */
-			break;
-		}
-		case 0x11:
-		{
-			/* Outputs 8 - 15 */
-			break;
-		}
-		case 0x12:
-		{
-			/* Outputs 16 - 23 */
-			break;
-		}
-		case 0x20:
-		{
-			/* Outputs 24 - 31 */
-			break;
-		}
-		case 0x21:
-		{
-			/* Outputs 32 - 39 */
-			break;
-		}
-		case 0x22:
-		{
-			/* Outputs 40 - 47 */
-			break;
-		}
-		case 0x30:
-		{
-			m_sn->write(space, 0, data & 0xff);
-			break;
-		}
-		case 0x31:
-		{
-			/* Only JPM knows about the other bits... */
-			m_floppy->get_device()->ss_w(BIT(data, 3));
-
-			// one of those bits will probably control the motor, we just let it run all the time for now
-			m_floppy->get_device()->mon_w(0);
-			break;
-		}
-		case 0x32:
-		{
-			/* Watchdog? */
-			break;
-		}
-		case 0x33:
-		{
-			/* Dunno */
-			break;
-		}
-		default:
-		{
-			osd_printf_debug("Unknown IO W:0x%x with %x\n", 0xc0000 + (offset * 2), data);
-		}
-	}
+	output().set_value("led_0", BIT(data, 0)); // cash in (ten up: cash in)
+	output().set_value("led_1", BIT(data, 1)); // cash out (ten up: cash out)
+	output().set_value("led_2", BIT(data, 2));
+	output().set_value("led_3", BIT(data, 3));
+	output().set_value("led_4", BIT(data, 4));
+	output().set_value("led_5", BIT(data, 5));
+	output().set_value("led_6", BIT(data, 6)); // (ten up: 10p/100p drive)
+	output().set_value("led_7", BIT(data, 7));
 }
 
+WRITE8_MEMBER( guab_state::output2_w )
+{
+	output().set_value("led_8", BIT(data, 0));
+	output().set_value("led_9", BIT(data, 1));
+	output().set_value("led_10", BIT(data, 2)); // start (ten up: start)
+	output().set_value("led_11", BIT(data, 3)); // (ten up: feature 6)
+	output().set_value("led_12", BIT(data, 4)); // (ten up: feature 11)
+	output().set_value("led_13", BIT(data, 5)); // (ten up: feature 13)
+	output().set_value("led_14", BIT(data, 6)); // lamp a (ten up: feature 12)
+	output().set_value("led_15", BIT(data, 7)); // lamp b (ten up: pass)
+}
 
-/*************************************
- *
- *  68000 CPU memory handlers
- *
- *************************************/
-
-static ADDRESS_MAP_START( guab_map, AS_PROGRAM, 16, guab_state )
-	AM_RANGE(0x000000, 0x00ffff) AM_ROM
-	AM_RANGE(0x040000, 0x04ffff) AM_ROM AM_REGION("maincpu", 0x10000)
-	AM_RANGE(0x0c0000, 0x0c007f) AM_READWRITE(io_r, io_w)
-	AM_RANGE(0x0c0080, 0x0c0083) AM_NOP /* ACIA 1 */
-	AM_RANGE(0x0c00a0, 0x0c00a3) AM_NOP /* ACIA 2 */
-	AM_RANGE(0x0c00c0, 0x0c00cf) AM_DEVREADWRITE8("6840ptm", ptm6840_device, read, write, 0xff)
-	AM_RANGE(0x0c00e0, 0x0c00e7) AM_DEVREADWRITE8("fdc", wd1773_t, read, write, 0x00ff)
-	AM_RANGE(0x080000, 0x080fff) AM_RAM
-	AM_RANGE(0x100000, 0x100003) AM_READWRITE(ef9369_r, ef9369_w)
-	AM_RANGE(0x800000, 0xb0ffff) AM_READWRITE(guab_tms34061_r, guab_tms34061_w)
-	AM_RANGE(0xb10000, 0xb1ffff) AM_RAM
-	AM_RANGE(0xb80000, 0xb8ffff) AM_RAM
-	AM_RANGE(0xb90000, 0xb9ffff) AM_RAM
-ADDRESS_MAP_END
-
-
-/*************************************
- *
- *  Port definitions
- *
- *************************************/
-
-static INPUT_PORTS_START( guab )
-	PORT_START("IN0")
-	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN3 )   PORT_NAME("50p") PORT_CHANGED_MEMBER(DEVICE_SELF, guab_state,coin_inserted, (void *)50)
-	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN4 )   PORT_NAME("100p") PORT_CHANGED_MEMBER(DEVICE_SELF, guab_state,coin_inserted, (void *)100)
-	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_NAME("Back door") PORT_CODE(KEYCODE_R) PORT_TOGGLE
-	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_NAME("Cash door") PORT_CODE(KEYCODE_T) PORT_TOGGLE
-	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_NAME("Key switch") PORT_CODE(KEYCODE_Y) PORT_TOGGLE
-	PORT_BIT( 0x20, IP_ACTIVE_HIGH,IPT_UNUSED )  PORT_NAME("50p level")
-	PORT_BIT( 0x40, IP_ACTIVE_HIGH,IPT_UNUSED )  PORT_NAME("100p level")
-	PORT_BIT( 0x80, IP_ACTIVE_HIGH,IPT_UNUSED )
-
-	PORT_START("IN1")
-	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
-	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
-	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_START1 )
-	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
-	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED )
-	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
-	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("A")
-	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("B")
+WRITE8_MEMBER( guab_state::output3_w )
+{
+	output().set_value("led_16", BIT(data, 0)); // select (ten up: collect)
+	output().set_value("led_17", BIT(data, 1)); // (ten up: feature 14)
+	output().set_value("led_18", BIT(data, 2)); // (ten up: feature 9)
+	output().set_value("led_19", BIT(data, 3)); //   (ten up: lamp a)
+	output().set_value("led_20", BIT(data, 4)); // lamp c (ten up: lamp b)
+	output().set_value("led_21", BIT(data, 5)); // lamp d (ten up: lamp c)
+	output().set_value("led_22", BIT(data, 6));
+	output().set_value("led_23", BIT(data, 7));
+}
 
-	PORT_START("IN2")
-	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("Select")
-	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
-	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
-	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
-	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("C")
-	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("D")
-	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN1 )   PORT_NAME("10p") PORT_CHANGED_MEMBER(DEVICE_SELF, guab_state,coin_inserted, (void *)10)
-	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_COIN2 )   PORT_NAME("20p") PORT_CHANGED_MEMBER(DEVICE_SELF, guab_state,coin_inserted, (void *)20)
-INPUT_PORTS_END
+WRITE8_MEMBER( guab_state::output4_w )
+{
+	output().set_value("led_24", BIT(data, 0)); // feature 1 (ten up: feature 1)
+	output().set_value("led_25", BIT(data, 1)); // feature 2 (ten up: feature 10)
+	output().set_value("led_26", BIT(data, 2)); // feature 3 (ten up: feature 7)
+	output().set_value("led_27", BIT(data, 3)); // feature 4 (ten up: feature 2)
+	output().set_value("led_28", BIT(data, 4)); // feature 5 (ten up: feature 8)
+	output().set_value("led_29", BIT(data, 5)); // feature 6 (ten up: feature 3)
+	output().set_value("led_30", BIT(data, 6)); // feature 7 (ten up: feature 4)
+	output().set_value("led_31", BIT(data, 7)); // feature 8 (ten up: feature 5)
+}
 
-static INPUT_PORTS_START( tenup )
-	PORT_START("IN0")
-	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN3 )   PORT_NAME("50p") PORT_CHANGED_MEMBER(DEVICE_SELF, guab_state,coin_inserted, (void *)50)
-	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN4 )   PORT_NAME("100p") PORT_CHANGED_MEMBER(DEVICE_SELF, guab_state,coin_inserted, (void *)100)
-	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_NAME("Back door") PORT_CODE(KEYCODE_R) PORT_TOGGLE
-	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_NAME("Cash door") PORT_CODE(KEYCODE_T) PORT_TOGGLE
-	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_NAME("Key switch") PORT_CODE(KEYCODE_Y) PORT_TOGGLE
-	PORT_BIT( 0x20, IP_ACTIVE_HIGH,IPT_UNUSED )  PORT_NAME("10p level")
-	PORT_BIT( 0x40, IP_ACTIVE_HIGH,IPT_UNUSED )  PORT_NAME("100p level")
-	PORT_BIT( 0x80, IP_ACTIVE_HIGH,IPT_UNUSED )
+WRITE8_MEMBER( guab_state::output5_w )
+{
+	output().set_value("led_32", BIT(data, 0));
+	output().set_value("led_33", BIT(data, 1));
+	output().set_value("led_34", BIT(data, 2));
+	output().set_value("led_35", BIT(data, 3));
+	output().set_value("led_36", BIT(data, 4));
+	output().set_value("led_37", BIT(data, 5));
+	output().set_value("led_38", BIT(data, 6));
+	output().set_value("led_39", BIT(data, 7)); // mech lamp (ten up: mech lamp)
+}
 
-	PORT_START("IN1")
-	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
-	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
-	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_START1 )
-	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
-	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED )
-	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
-	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
-	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("Pass")
+WRITE8_MEMBER( guab_state::output6_w )
+{
+	output().set_value("led_40", BIT(data, 0));
+	output().set_value("led_41", BIT(data, 1));
+	output().set_value("led_42", BIT(data, 2));
+	output().set_value("led_43", BIT(data, 3));
+	output().set_value("led_44", BIT(data, 4)); // 50p drive (ten up: 10p drive)
+	output().set_value("led_45", BIT(data, 5)); // 100p drive (ten up: 100p drive)
+	output().set_value("led_46", BIT(data, 6));
+	output().set_value("led_47", BIT(data, 7));
+}
 
-	PORT_START("IN2")
-	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("Collect")
-	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
-	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
-	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("A")
-	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("B")
-	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("C")
-	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN1 )   PORT_NAME("10p")  PORT_CHANGED_MEMBER(DEVICE_SELF, guab_state,coin_inserted, (void *)10)
-	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_COIN2 )   PORT_NAME("20p")  PORT_CHANGED_MEMBER(DEVICE_SELF, guab_state,coin_inserted, (void *)20)
-INPUT_PORTS_END
 
+//**************************************************************************
+//  AUDIO
+//**************************************************************************
 
-/*************************************
- *
- *  Machine driver
- *
- *************************************/
+READ8_MEMBER( guab_state::sn76489_ready_r )
+{
+	// bit 7 connected to sn76489 ready output (0 = ready)
+	return ~(m_sn->ready_r() << 7);
+}
 
-void guab_state::machine_start()
+WRITE8_MEMBER( guab_state::sn76489_buffer_w )
 {
-	m_fdc->set_floppy(m_floppy->get_device());
+	m_sound_buffer = data;
 }
 
+
+//**************************************************************************
+//  FLOPPY DRIVE
+//**************************************************************************
+
 FLOPPY_FORMATS_MEMBER( guab_state::floppy_formats )
 	FLOPPY_GUAB_FORMAT
 FLOPPY_FORMATS_END
@@ -494,6 +440,11 @@ static SLOT_INTERFACE_START( guab_floppies )
 	SLOT_INTERFACE("dd", FLOPPY_35_DD)
 SLOT_INTERFACE_END
 
+
+//**************************************************************************
+//  MACHINE DEFINTIONS
+//**************************************************************************
+
 static MACHINE_CONFIG_START( guab, guab_state )
 	/* TODO: Verify clock */
 	MCFG_CPU_ADD("maincpu", M68000, 8000000)
@@ -508,12 +459,15 @@ static MACHINE_CONFIG_START( guab, guab_state )
 	MCFG_SCREEN_UPDATE_DRIVER(guab_state, screen_update_guab)
 	MCFG_SCREEN_PALETTE("palette")
 
-	MCFG_PALETTE_ADD("palette", 16)
+	MCFG_PALETTE_ADD("palette", ef9369_device::NUMCOLORS)
+
+	MCFG_EF9369_ADD("ef9369")
+	MCFG_EF9369_COLOR_UPDATE_CB(guab_state, ef9369_color_update)
 
 	MCFG_DEVICE_ADD("tms34061", TMS34061, 0)
 	MCFG_TMS34061_ROWSHIFT(8)  /* VRAM address is (row << rowshift) | col */
-	MCFG_TMS34061_VRAM_SIZE(0x40000) /* size of video RAM */
-	MCFG_TMS34061_INTERRUPT_CB(WRITELINE(guab_state, generate_tms34061_interrupt))      /* interrupt gen callback */
+	MCFG_TMS34061_VRAM_SIZE(0x40000)
+	MCFG_TMS34061_INTERRUPT_CB(INPUTLINE("maincpu", 5))
 
 	MCFG_SPEAKER_STANDARD_MONO("mono")
 
@@ -521,28 +475,52 @@ static MACHINE_CONFIG_START( guab, guab_state )
 	MCFG_SOUND_ADD("snsnd", SN76489, 2000000)
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
 
-	/* 6840 PTM */
-	MCFG_DEVICE_ADD("6840ptm", PTM6840, 0)
-	MCFG_PTM6840_INTERNAL_CLOCK(1000000)
+	MCFG_DEVICE_ADD("6840ptm", PTM6840, 1000000)
 	MCFG_PTM6840_EXTERNAL_CLOCKS(0, 0, 0)
-	MCFG_PTM6840_IRQ_CB(WRITELINE(guab_state, ptm_irq))
+	MCFG_PTM6840_IRQ_CB(INPUTLINE("maincpu", 3))
+
+	MCFG_DEVICE_ADD("i8255_1", I8255, 0)
+	MCFG_I8255_IN_PORTA_CB(IOPORT("IN0"))
+	MCFG_I8255_IN_PORTB_CB(IOPORT("IN1"))
+	MCFG_I8255_IN_PORTC_CB(IOPORT("IN2"))
+
+	MCFG_DEVICE_ADD("i8255_2", I8255, 0)
+	MCFG_I8255_OUT_PORTA_CB(WRITE8(guab_state, output1_w))
+	MCFG_I8255_OUT_PORTB_CB(WRITE8(guab_state, output2_w))
+	MCFG_I8255_OUT_PORTC_CB(WRITE8(guab_state, output3_w))
+
+	MCFG_DEVICE_ADD("i8255_3", I8255, 0)
+	MCFG_I8255_OUT_PORTA_CB(WRITE8(guab_state, output4_w))
+	MCFG_I8255_OUT_PORTB_CB(WRITE8(guab_state, output5_w))
+	MCFG_I8255_OUT_PORTC_CB(WRITE8(guab_state, output6_w))
+
+	MCFG_DEVICE_ADD("i8255_4", I8255, 0)
+	MCFG_I8255_IN_PORTA_CB(READ8(guab_state, sn76489_ready_r))
+	MCFG_I8255_OUT_PORTA_CB(WRITE8(guab_state, sn76489_buffer_w))
+	MCFG_I8255_OUT_PORTB_CB(WRITE8(guab_state, system_w))
+	MCFG_I8255_IN_PORTC_CB(READ8(guab_state, watchdog_r))
+	MCFG_I8255_OUT_PORTC_CB(WRITE8(guab_state, watchdog_w))
+
+	MCFG_DEVICE_ADD("acia6850_1", ACIA6850, 0)
+
+	MCFG_DEVICE_ADD("acia6850_2", ACIA6850, 0)
 
 	// floppy
 	MCFG_WD1773_ADD("fdc", 8000000)
-	MCFG_WD_FDC_DRQ_CALLBACK(INPUTLINE("maincpu", INT_FLOPPYCTRL))
+	MCFG_WD_FDC_DRQ_CALLBACK(INPUTLINE("maincpu", 6))
 
 	MCFG_FLOPPY_DRIVE_ADD("fdc:0", guab_floppies, "dd", guab_state::floppy_formats)
 	MCFG_SLOT_FIXED(true)
 
 	MCFG_SOFTWARE_LIST_ADD("floppy_list", "guab")
+
+	MCFG_DEFAULT_LAYOUT(layout_guab)
 MACHINE_CONFIG_END
 
 
-/*************************************
- *
- *  ROM definition(s)
- *
- *************************************/
+//**************************************************************************
+//  ROM DEFINITIONS
+//**************************************************************************
 
 ROM_START( guab )
 	ROM_REGION( 0x20000, "maincpu", 0 )
@@ -567,12 +545,11 @@ ROM_START( tenup )
 ROM_END
 
 
-/*************************************
- *
- *  Game driver(s)
- *
- *************************************/
+//**************************************************************************
+//  SYSTEM DRIVERS
+//**************************************************************************
 
-GAME( 1986, guab,     0, guab, guab,  driver_device, 0, ROT0, "JPM", "Give us a Break",      0 )
-GAME( 1986, crisscrs, 0, guab, guab,  driver_device, 0, ROT0, "JPM", "Criss Cross (Sweden)", MACHINE_NOT_WORKING )
-GAME( 1988, tenup,    0, guab, tenup, driver_device, 0, ROT0, "JPM", "Ten Up",               0 )
+//    YEAR  NAME      PARENT  MACHINE  INPUT  CLASS          INIT  ROTATION  COMPANY  FULLNAME                FLAGS
+GAME( 1986, guab,     0,      guab,    guab,  driver_device, 0,    ROT0,     "JPM",   "Give us a Break",      0 )
+GAME( 1986, crisscrs, 0,      guab,    guab,  driver_device, 0,    ROT0,     "JPM",   "Criss Cross (Sweden)", MACHINE_NOT_WORKING )
+GAME( 1988, tenup,    0,      guab,    tenup, driver_device, 0,    ROT0,     "JPM",   "Ten Up",               0 )
diff --git a/src/mame/drivers/hanaawas.cpp b/src/mame/drivers/hanaawas.cpp
index b287807..b45ef16 100644
--- a/src/mame/drivers/hanaawas.cpp
+++ b/src/mame/drivers/hanaawas.cpp
@@ -37,17 +37,31 @@ READ8_MEMBER(hanaawas_state::hanaawas_input_port_0_r)
 	int i, ordinal = 0;
 	uint16_t buttons = 0;
 
+	// TODO: key matrix seems identical to speedatk.cpp, needs merging
+	if(m_coin_impulse > 0)
+	{
+		m_coin_impulse--;
+		return 0x80;
+	}
+
+	if((ioport("COINS")->read() & 1) || (ioport("COINS")->read() & 2))
+	{
+		m_coin_impulse = m_coin_settings*2;
+		m_coin_impulse--;
+		return 0x80;
+	}
+
 	switch (m_mux)
 	{
-	case 1: /* start buttons */
-		buttons = ioport("START")->read();
-		break;
-	case 2: /* player 1 buttons */
-		buttons = ioport("P1")->read();
-		break;
-	case 4: /* player 2 buttons */
-		buttons = ioport("P2")->read();
-		break;
+		case 1: /* start buttons */
+			buttons = ioport("START")->read();
+			break;
+		case 2: /* player 1 buttons */
+			buttons = ioport("P1")->read();
+			break;
+		case 4: /* player 2 buttons */
+			buttons = ioport("P2")->read();
+			break;
 	}
 
 
@@ -62,7 +76,7 @@ READ8_MEMBER(hanaawas_state::hanaawas_input_port_0_r)
 		}
 	}
 
-	return (ioport("IN0")->read() & 0xf0) | ordinal;
+	return ordinal;
 }
 
 WRITE8_MEMBER(hanaawas_state::hanaawas_inputs_mux_w)
@@ -75,6 +89,11 @@ WRITE8_MEMBER(hanaawas_state::irq_ack_w)
 	m_maincpu->set_input_line(0,CLEAR_LINE);
 }
 
+WRITE8_MEMBER(hanaawas_state::key_matrix_status_w)
+{
+	if((data & 0xf0) == 0x40) //coinage setting command
+		m_coin_settings = data & 0xf;
+}
 
 static ADDRESS_MAP_START( hanaawas_map, AS_PROGRAM, 8, hanaawas_state )
 	AM_RANGE(0x0000, 0x2fff) AM_ROM
@@ -90,19 +109,16 @@ ADDRESS_MAP_END
 static ADDRESS_MAP_START( io_map, AS_IO, 8, hanaawas_state )
 	ADDRESS_MAP_GLOBAL_MASK(0xff)
 	AM_RANGE(0x00, 0x00) AM_READWRITE(hanaawas_input_port_0_r, hanaawas_inputs_mux_w)
-	AM_RANGE(0x01, 0x01) AM_READNOP /* r bit 1: status ready, presumably of the input mux device / w = configure device? */
+	AM_RANGE(0x01, 0x01) AM_READNOP AM_WRITE(key_matrix_status_w) /* r bit 1: status ready, presumably of the input mux device / w = configure device? */
 	AM_RANGE(0x10, 0x10) AM_DEVREAD("aysnd", ay8910_device, data_r)
 	AM_RANGE(0x10, 0x11) AM_DEVWRITE("aysnd", ay8910_device, address_data_w)
 	AM_RANGE(0xc0, 0xc0) AM_WRITENOP // watchdog
 ADDRESS_MAP_END
 
 static INPUT_PORTS_START( hanaawas )
-	PORT_START("IN0")
-	PORT_BIT( 0x0f, IP_ACTIVE_HIGH, IPT_SPECIAL )
-	PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNKNOWN )
-	PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNKNOWN )
-	PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_UNKNOWN )
-	PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_COIN1 ) PORT_IMPULSE(1)
+	PORT_START("COINS")
+	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_COIN1 ) PORT_IMPULSE(1)
+	PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_COIN2 ) PORT_IMPULSE(1)
 
 	PORT_START("DSW")
 	PORT_DIPNAME( 0x01, 0x00, DEF_STR( Unknown ) )
@@ -184,6 +200,8 @@ GFXDECODE_END
 void hanaawas_state::machine_start()
 {
 	save_item(NAME(m_mux));
+	save_item(NAME(m_coin_settings));
+	save_item(NAME(m_coin_impulse));
 }
 
 void hanaawas_state::machine_reset()
diff --git a/src/mame/drivers/hazeltin.cpp b/src/mame/drivers/hazeltin.cpp
index b820ca2..6c4a201 100644
--- a/src/mame/drivers/hazeltin.cpp
+++ b/src/mame/drivers/hazeltin.cpp
@@ -7,8 +7,16 @@
 
     perliminary driver by Ryan Holtz
 
-TODO:
-    - pretty much everything
+TODO (roughly in order of importance):
+    - Figure out the correct keyboard decoding.
+    - Proper RS232 hookup.
+    - Iron out proper horizontal and vertical start/end values.
+    - Hook up /FGBIT, REV FLD FRAME, and REV VIDEO SELECT lines on video
+      board.
+    - Reimplement logic probe (since removed) as a netlist device so other
+      devs can use it.
+    - Implement /BRESET line in netlist to possibly smooth out some sync
+      issues.
 
 References:
     [1]: Hazeltine_1500_Series_Maintenance_Manual_Dec77.pdf, on Bitsavers
@@ -17,64 +25,35 @@ References:
 
 #include "emu.h"
 #include "cpu/i8085/i8085.h"
-#include "machine/7400.h"
-#include "machine/7404.h"
-#include "machine/7474.h"
-#include "machine/74161.h"
-#include "machine/74175.h"
-#include "machine/82s129.h"
-#include "machine/am2847.h"
 #include "machine/ay31015.h"
 #include "machine/clock.h"
 #include "machine/com8116.h"
-#include "machine/dm9334.h"
 #include "machine/kb3600.h"
+#include "machine/netlist.h"
+#include "machine/nl_hazelvid.h"
+#include "netlist/devices/net_lib.h"
 
 #define CPU_TAG         "maincpu"
+#define NETLIST_TAG     "videobrd"
 #define UART_TAG        "uart"
 #define BAUDGEN_TAG     "baudgen"
 #define KBDC_TAG        "ay53600"
-#define CHARRAM_TAG     "chrram"
 #define CHARROM_TAG     "chargen"
 #define BAUDPORT_TAG    "baud"
 #define MISCPORT_TAG    "misc"
 #define MISCKEYS_TAG    "misc_keys"
 #define SCREEN_TAG      "screen"
-#define TMS3409A_TAG    "u67"
-#define TMS3409B_TAG    "u57"
-#define DOTCLK_TAG      "dotclk"
-#define DOTCLK_DISP_TAG "dotclk_dispatch"
-#define CHAR_CTR_CLK_TAG "ch_bucket_ctr_clk"
-#define U58_TAG         "u58"
-#define U59_TAG         "u59"
-#define VID_PROM_ADDR_RESET_TAG "u59_y5"
-#define U61_TAG         "u61"
-#define U68_TAG         "u68"
-#define U69_PROMMSB_TAG "u69"
-#define U70_PROMLSB_TAG "u70"
-#define U70_TC_LINE_TAG "u70_tc"
-#define U71_PROM_TAG    "u71"
-#define U72_PROMDEC_TAG "u72"
-#define U81_TAG         "u81"
-#define U83_TAG         "u83"
-#define U84_DIV11_TAG   "u84"
-#define U85_VERT_DR_UB_TAG "u85"
-#define U87_TAG         "u87"
-#define U88_DIV9_TAG    "u88"
-#define U90_DIV14_TAG   "u90"
 #define BAUD_PROM_TAG   "u39"
+#define NL_PROM_TAG     "videobrd:u71"
+#define NL_EPROM_TAG    "videobrd:u78"
+#define VIDEO_PROM_TAG  "u71"
+#define CHAR_EPROM_TAG  "u78"
+#define VIDEO_OUT_TAG   "videobrd:video_out"
+#define VBLANK_OUT_TAG  "videobrd:vblank"
+#define TVINTERQ_OUT_TAG "videobrd:tvinterq"
 
-// Number of cycles to burn when fetching the next row of characters into the line buffer:
-// CPU clock is 18MHz / 9
-// Dot clock is 33.264MHz / 2
-// 9 dots per character
-// 80 visible characters per line
-// Total duration of fetch: 1440 33.264MHz clock cycles
-//
-//     2*9*80                    1         1440 * XTAL_2MHz
-// -------------- divided by ---------  =  ----------------  =  86.5 main CPU cycles per line fetch
-// XTAL_33_264MHz            XTAL_2MHz      XTAL_33_264MHz
-#define LINE_FETCH_CYCLES   (87)
+#define VIDEO_CLOCK     (XTAL_33_264MHz/2)
+#define VIDEOBRD_CLOCK  (XTAL_33_264MHz*30)
 
 #define SR2_FULL_DUPLEX (0x01)
 #define SR2_UPPER_ONLY  (0x08)
@@ -91,9 +70,7 @@ References:
 
 #define SCREEN_VTOTAL   (28*11)
 #define SCREEN_VDISP    (24*11)
-#define SCREEN_VSTART   (0)
-
-#define VERT_UB_LINE    (24*11+8)
+#define SCREEN_VSTART   (3*11)
 
 class hazl1500_state : public driver_device
 {
@@ -101,53 +78,70 @@ public:
 	hazl1500_state(const machine_config &mconfig, device_type type, const char *tag)
 		: driver_device(mconfig, type, tag)
 		, m_maincpu(*this, CPU_TAG)
+		, m_video_board(*this, NETLIST_TAG)
+		, m_u71(*this, NL_PROM_TAG)
+		, m_u78(*this, NL_EPROM_TAG)
+		, m_u9(*this, "videobrd:u9")
+		, m_u10(*this, "videobrd:u10")
+		, m_u11(*this, "videobrd:u11")
+		, m_u12(*this, "videobrd:u12")
+		, m_u13(*this, "videobrd:u13")
+		, m_u14(*this, "videobrd:u14")
+		, m_u15(*this, "videobrd:u15")
+		, m_u16(*this, "videobrd:u16")
+		, m_u22(*this, "videobrd:u22")
+		, m_u23(*this, "videobrd:u23")
+		, m_u24(*this, "videobrd:u24")
+		, m_u25(*this, "videobrd:u25")
+		, m_u26(*this, "videobrd:u26")
+		, m_u27(*this, "videobrd:u27")
+		, m_u28(*this, "videobrd:u28")
+		, m_u29(*this, "videobrd:u29")
+		, m_cpu_db0(*this, "videobrd:cpu_db0")
+		, m_cpu_db1(*this, "videobrd:cpu_db1")
+		, m_cpu_db2(*this, "videobrd:cpu_db2")
+		, m_cpu_db3(*this, "videobrd:cpu_db3")
+		, m_cpu_db4(*this, "videobrd:cpu_db4")
+		, m_cpu_db5(*this, "videobrd:cpu_db5")
+		, m_cpu_db6(*this, "videobrd:cpu_db6")
+		, m_cpu_db7(*this, "videobrd:cpu_db7")
+		, m_cpu_ba4(*this, "videobrd:cpu_ba4")
+		, m_cpu_iowq(*this, "videobrd:cpu_iowq")
+		, m_video_out(*this, VIDEO_OUT_TAG)
+		, m_vblank_out(*this, VBLANK_OUT_TAG)
+		, m_tvinterq_out(*this, TVINTERQ_OUT_TAG)
 		, m_uart(*this, UART_TAG)
 		, m_kbdc(*this, KBDC_TAG)
 		, m_baud_dips(*this, BAUDPORT_TAG)
 		, m_baud_prom(*this, BAUD_PROM_TAG)
 		, m_misc_dips(*this, MISCPORT_TAG)
 		, m_kbd_misc_keys(*this, MISCKEYS_TAG)
-		, m_char_ram(*this, CHARRAM_TAG)
-		, m_char_rom(*this, CHARROM_TAG)
-		, m_line_buffer_lsb(*this, TMS3409A_TAG)
-		, m_line_buffer_msb(*this, TMS3409B_TAG)
-		, m_dotclk(*this, DOTCLK_TAG)
-		, m_vid_prom_msb(*this, U69_PROMMSB_TAG)
-		, m_vid_prom_lsb(*this, U70_PROMLSB_TAG)
-		, m_vid_prom(*this, U71_PROM_TAG)
-		, m_u59(*this, U59_TAG)
-		, m_u83(*this, U83_TAG)
-		, m_char_y(*this, U84_DIV11_TAG)
-		, m_char_x(*this, U88_DIV9_TAG)
-		, m_vid_div14(*this, U90_DIV14_TAG)
-		, m_vid_decode(*this, U72_PROMDEC_TAG)
-		, m_u58(*this, U58_TAG)
-		, m_u68(*this, U68_TAG)
-		, m_u81(*this, U81_TAG)
-		, m_u87(*this, U87_TAG)
-		, m_u61(*this, U61_TAG)
 		, m_screen(*this, SCREEN_TAG)
-		, m_hblank_timer(nullptr)
-		, m_scanline_timer(nullptr)
+		, m_iowq_timer(nullptr)
 		, m_status_reg_3(0)
 		, m_kbd_status_latch(0)
 		, m_refresh_address(0)
-		, m_vpos(0)
-		, m_hblank(false)
-		, m_vblank(false)
-		, m_delayed_vblank(false)
+		, m_screen_buf(nullptr)
+		, m_last_beam(0.0)
+		, m_last_hpos(0)
+		, m_last_vpos(0)
+		, m_last_fraction(0.0)
 	{
 	}
 
-	//m_maincpu->adjust_icount(-14);
-
 	virtual void machine_start() override;
 	virtual void machine_reset() override;
+	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+
+	static const device_timer_id TIMER_IOWQ = 0;
 
 	uint32_t screen_update_hazl1500(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
 
 	DECLARE_WRITE_LINE_MEMBER(com5016_fr_w);
 
+	DECLARE_READ8_MEMBER(ram_r);
+	DECLARE_WRITE8_MEMBER(ram_w);
+
 	DECLARE_READ8_MEMBER(system_test_r); // noted as "for use with auto test equip" in flowchart on pg. 30, ref[1], jumps to 0x8000 if bit 0 is unset
 	DECLARE_READ8_MEMBER(status_reg_2_r);
 	DECLARE_WRITE8_MEMBER(status_reg_3_w);
@@ -162,18 +156,45 @@ public:
 	DECLARE_WRITE_LINE_MEMBER(ay3600_data_ready_w);
 
 	DECLARE_WRITE8_MEMBER(refresh_address_w);
-	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
 
-	static const device_timer_id TIMER_HBLANK = 0;
-	static const device_timer_id TIMER_SCANLINE = 1;
+	NETDEV_ANALOG_CALLBACK_MEMBER(video_out_cb);
+	NETDEV_ANALOG_CALLBACK_MEMBER(vblank_cb);
+	NETDEV_ANALOG_CALLBACK_MEMBER(tvinterq_cb);
 
 private:
-	void check_tv_interrupt();
-	void update_tv_unblank();
-	void scanline_tick();
-	void draw_scanline(uint32_t *pix);
-
 	required_device<cpu_device> m_maincpu;
+	required_device<netlist_mame_device_t> m_video_board;
+	required_device<netlist_mame_rom_t> m_u71;
+	required_device<netlist_mame_rom_t> m_u78;
+	required_device<netlist_ram_pointer_t> m_u9;
+	required_device<netlist_ram_pointer_t> m_u10;
+	required_device<netlist_ram_pointer_t> m_u11;
+	required_device<netlist_ram_pointer_t> m_u12;
+	required_device<netlist_ram_pointer_t> m_u13;
+	required_device<netlist_ram_pointer_t> m_u14;
+	required_device<netlist_ram_pointer_t> m_u15;
+	required_device<netlist_ram_pointer_t> m_u16;
+	required_device<netlist_ram_pointer_t> m_u22;
+	required_device<netlist_ram_pointer_t> m_u23;
+	required_device<netlist_ram_pointer_t> m_u24;
+	required_device<netlist_ram_pointer_t> m_u25;
+	required_device<netlist_ram_pointer_t> m_u26;
+	required_device<netlist_ram_pointer_t> m_u27;
+	required_device<netlist_ram_pointer_t> m_u28;
+	required_device<netlist_ram_pointer_t> m_u29;
+	required_device<netlist_mame_logic_input_t> m_cpu_db0;
+	required_device<netlist_mame_logic_input_t> m_cpu_db1;
+	required_device<netlist_mame_logic_input_t> m_cpu_db2;
+	required_device<netlist_mame_logic_input_t> m_cpu_db3;
+	required_device<netlist_mame_logic_input_t> m_cpu_db4;
+	required_device<netlist_mame_logic_input_t> m_cpu_db5;
+	required_device<netlist_mame_logic_input_t> m_cpu_db6;
+	required_device<netlist_mame_logic_input_t> m_cpu_db7;
+	required_device<netlist_mame_logic_input_t> m_cpu_ba4;
+	required_device<netlist_mame_logic_input_t> m_cpu_iowq;
+	required_device<netlist_mame_analog_output_t> m_video_out;
+	required_device<netlist_mame_analog_output_t> m_vblank_out;
+	required_device<netlist_mame_analog_output_t> m_tvinterq_out;
 	required_device<ay31015_device> m_uart;
 	required_device<ay3600_device> m_kbdc;
 	required_ioport m_baud_dips;
@@ -181,82 +202,50 @@ private:
 	required_ioport m_misc_dips;
 	required_ioport m_kbd_misc_keys;
 
-	required_shared_ptr<uint8_t> m_char_ram;
-	required_region_ptr<uint8_t> m_char_rom;
-	required_device<tms3409_device> m_line_buffer_lsb;
-	required_device<tms3409_device> m_line_buffer_msb;
-	required_device<clock_device> m_dotclk;
-	required_device<ttl74161_device> m_vid_prom_msb;
-	required_device<ttl74161_device> m_vid_prom_lsb;
-	required_device<prom82s129_device> m_vid_prom;
-	required_device<ttl7404_device> m_u59;
-	required_device<ttl7400_device> m_u83;
-	required_device<ttl74161_device> m_char_y;
-	required_device<ttl74161_device> m_char_x;
-	required_device<ttl74161_device> m_vid_div14;
-	required_device<dm9334_device> m_vid_decode;
-	required_device<ttl74175_device> m_u58;
-	required_device<ttl74175_device> m_u68;
-	required_device<ttl74175_device> m_u81;
-	required_device<ttl7404_device> m_u87;
-	required_device<ttl7404_device> m_u61;
-
 	required_device<screen_device> m_screen;
 
-	std::unique_ptr<uint32_t[]> m_screen_pixbuf;
-
-	emu_timer *m_hblank_timer;
-	emu_timer *m_scanline_timer;
+	emu_timer* m_iowq_timer;
 
 	uint8_t m_status_reg_3;
 	uint8_t m_kbd_status_latch;
 
 	uint8_t m_refresh_address;
-	uint16_t m_vpos;
-	bool m_hblank;
-	bool m_vblank;
-	bool m_delayed_vblank;
+
+	std::unique_ptr<float[]> m_screen_buf;
+
+	double m_last_beam;
+	int m_last_hpos;
+	int m_last_vpos;
+	double m_last_fraction;
 };
 
 void hazl1500_state::machine_start()
 {
-	m_hblank_timer = timer_alloc(TIMER_HBLANK);
-	m_hblank_timer->adjust(attotime::never);
+	m_screen_buf = std::make_unique<float[]>(SCREEN_HTOTAL * SCREEN_VTOTAL);
 
-	m_scanline_timer = timer_alloc(TIMER_SCANLINE);
-	m_scanline_timer->adjust(attotime::never);
-
-	m_screen_pixbuf = std::make_unique<uint32_t[]>(SCREEN_HTOTAL * SCREEN_VTOTAL);
+	m_iowq_timer = timer_alloc(TIMER_IOWQ);
+	m_iowq_timer->adjust(attotime::never);
 
 	save_item(NAME(m_status_reg_3));
 	save_item(NAME(m_kbd_status_latch));
 	save_item(NAME(m_refresh_address));
-	save_item(NAME(m_vpos));
-	save_item(NAME(m_hblank));
-	save_item(NAME(m_vblank));
-	save_item(NAME(m_delayed_vblank));
+	save_item(NAME(m_last_beam));
+	save_item(NAME(m_last_hpos));
+	save_item(NAME(m_last_vpos));
+	save_item(NAME(m_last_fraction));
 }
 
 void hazl1500_state::machine_reset()
 {
 	m_status_reg_3 = 0;
 	m_kbd_status_latch = 0;
-
-	m_refresh_address = 0;
-	m_screen->reset_origin(0, 0);
-	m_vpos = m_screen->vpos();
-	m_vblank = (m_vpos >= SCREEN_VDISP);
-	m_delayed_vblank = m_vpos < VERT_UB_LINE;
-	if (!m_vblank)
-		m_kbd_status_latch |= KBD_STATUS_TV_UB;
-	m_hblank = true;
-	m_hblank_timer->adjust(m_screen->time_until_pos(m_vpos, SCREEN_HSTART));
-	m_scanline_timer->adjust(m_screen->time_until_pos(m_vpos + 1, 0));
-
-	m_vid_prom_lsb->p_w(generic_space(), 0, 0);
-	m_vid_prom_msb->p_w(generic_space(), 0, 0);
 }
 
+void hazl1500_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+	m_cpu_iowq->write(1);
+	m_cpu_ba4->write(1);
+}
 
 WRITE_LINE_MEMBER( hazl1500_state::com5016_fr_w )
 {
@@ -266,10 +255,65 @@ WRITE_LINE_MEMBER( hazl1500_state::com5016_fr_w )
 
 uint32_t hazl1500_state::screen_update_hazl1500(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
 {
-	memcpy(&bitmap.pix32(0), &m_screen_pixbuf[0], sizeof(uint32_t) * SCREEN_HTOTAL * SCREEN_VTOTAL);
+	int last_index = m_last_vpos * SCREEN_HTOTAL + m_last_hpos;
+	while (last_index < SCREEN_HTOTAL * SCREEN_VTOTAL)
+	{
+		m_screen_buf[last_index++] = m_last_beam;
+	}
+	m_last_hpos = 0;
+	m_last_vpos = 0;
+
+	uint32_t pixindex = 0;
+	for (int y = 0; y < SCREEN_VTOTAL; y++)
+	{
+		uint32_t *scanline = &bitmap.pix32(y);
+		pixindex = y * SCREEN_HTOTAL;
+		for (int x = 0; x < SCREEN_HTOTAL; x++)
+			//*scanline++ = 0xff000000 | (uint8_t(m_screen_buf[pixindex++] * 0.5) * 0x010101);
+			*scanline++ = 0xff000000 | (uint8_t(m_screen_buf[pixindex++] * 63.0) * 0x010101);
+	}
+
 	return 0;
 }
 
+READ8_MEMBER( hazl1500_state::ram_r )
+{
+	const uint8_t* chips[2][8] =
+	{
+		{ m_u29->ptr(), m_u28->ptr(), m_u27->ptr(), m_u26->ptr(), m_u25->ptr(), m_u24->ptr(), m_u23->ptr(), m_u22->ptr() },
+		{ m_u16->ptr(), m_u15->ptr(), m_u14->ptr(), m_u13->ptr(), m_u12->ptr(), m_u11->ptr(), m_u10->ptr(), m_u9->ptr() }
+	};
+
+	int bank = ((offset & 0x400) != 0 ? 1 : 0);
+	const int byte_pos = (offset >> 3) & 0x7f;
+	const int bit_pos = offset & 7;
+
+	uint8_t ret = 0;
+	for (std::size_t bit = 0; bit < 8; bit++)
+		ret |= ((chips[bank][bit][byte_pos] >> bit_pos) & 1) << bit;
+
+	return ret;
+}
+
+WRITE8_MEMBER( hazl1500_state::ram_w )
+{
+	uint8_t* chips[2][8] =
+	{
+		{ m_u29->ptr(), m_u28->ptr(), m_u27->ptr(), m_u26->ptr(), m_u25->ptr(), m_u24->ptr(), m_u23->ptr(), m_u22->ptr() },
+		{ m_u16->ptr(), m_u15->ptr(), m_u14->ptr(), m_u13->ptr(), m_u12->ptr(), m_u11->ptr(), m_u10->ptr(), m_u9->ptr() }
+	};
+
+	int bank = ((offset & 0x400) != 0 ? 1 : 0);
+	const int byte_pos = (offset >> 3) & 0x7f;
+	const int bit_pos = offset & 7;
+
+	for (std::size_t bit = 0; bit < 8; bit++)
+	{
+		chips[bank][bit][byte_pos] &= ~(1 << bit_pos);
+		chips[bank][bit][byte_pos] |= ((data >> bit) & 1) << bit_pos;
+	}
+}
+
 READ8_MEMBER( hazl1500_state::system_test_r )
 {
 	return 0xff;
@@ -305,7 +349,6 @@ WRITE8_MEMBER( hazl1500_state::uart_w )
 
 READ8_MEMBER( hazl1500_state::kbd_status_latch_r )
 {
-	//printf("m_kbd_status_latch r: %02x\n", m_kbd_status_latch);
 	return m_kbd_status_latch;
 }
 
@@ -343,124 +386,94 @@ WRITE_LINE_MEMBER(hazl1500_state::ay3600_data_ready_w)
 		m_kbd_status_latch &= ~KBD_STATUS_KBDR;
 }
 
-void hazl1500_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+NETDEV_ANALOG_CALLBACK_MEMBER(hazl1500_state::vblank_cb)
 {
-	switch(id)
+	synchronize();
+	if (int(data) > 1)
+	{
+		m_kbd_status_latch &= ~KBD_STATUS_TV_UB;
+	}
+	else
 	{
-		case TIMER_HBLANK:
-			if (m_hblank)
-			{
-				m_hblank_timer->adjust(m_screen->time_until_pos(m_vpos, SCREEN_HSTART + SCREEN_HDISP));
-			}
-			else
-			{
-				m_hblank_timer->adjust(m_screen->time_until_pos((m_vpos + 1) % SCREEN_VTOTAL, SCREEN_HSTART));
-			}
-			m_hblank ^= 1;
-			break;
-
-		case TIMER_SCANLINE:
-		{
-			scanline_tick();
-			break;
-		}
+		m_kbd_status_latch |= KBD_STATUS_TV_UB;
 	}
 }
 
-WRITE8_MEMBER(hazl1500_state::refresh_address_w)
+NETDEV_ANALOG_CALLBACK_MEMBER(hazl1500_state::tvinterq_cb)
 {
-	m_refresh_address = data;
-	//printf("m_refresh_address %x, vpos %d, screen vpos %d\n", m_refresh_address, m_vpos, m_screen->vpos());
-}
-
-void hazl1500_state::check_tv_interrupt()
-{
-	uint8_t char_row = m_vpos % 11;
-	bool bit_match = char_row == 2 || char_row == 3;
-	bool tv_interrupt = bit_match && !m_delayed_vblank;
-	//printf("interrupt for line %d (%d): %s\n", m_vpos, char_row, tv_interrupt ? "yes" : "no");
-
-	m_kbd_status_latch &= ~KBD_STATUS_TV_INT;
-	m_kbd_status_latch |= tv_interrupt ? KBD_STATUS_TV_INT : 0;
-
-	m_maincpu->set_input_line(INPUT_LINE_IRQ0, tv_interrupt ? ASSERT_LINE : CLEAR_LINE);
-}
-
-void hazl1500_state::update_tv_unblank()
-{
-	if (!m_vblank)
+	synchronize();
+	if (int(data) > 1)
 	{
-		m_kbd_status_latch |= KBD_STATUS_TV_UB;
+		m_kbd_status_latch &= ~KBD_STATUS_TV_INT;
+		m_maincpu->set_input_line(INPUT_LINE_IRQ0, CLEAR_LINE);
 	}
 	else
 	{
-		m_kbd_status_latch &= ~KBD_STATUS_TV_UB;
+		m_kbd_status_latch |= KBD_STATUS_TV_INT;
+		m_maincpu->set_input_line(INPUT_LINE_IRQ0, ASSERT_LINE);
 	}
 }
 
-void hazl1500_state::scanline_tick()
+NETDEV_ANALOG_CALLBACK_MEMBER(hazl1500_state::video_out_cb)
 {
-	uint16_t old_vpos = m_vpos;
-	m_vpos = (m_vpos + 1) % SCREEN_VTOTAL;
-	m_vblank = (m_vpos >= SCREEN_VDISP);
-	m_delayed_vblank = m_vpos >= VERT_UB_LINE;
+	synchronize();
+	attotime second_fraction(0, time.attoseconds());
+	attotime frame_fraction(0, (second_fraction * 60).attoseconds());
+	attotime pixel_time = frame_fraction * (SCREEN_HTOTAL * SCREEN_VTOTAL);
+	int32_t pixel_index = (frame_fraction * (SCREEN_HTOTAL * SCREEN_VTOTAL)).seconds();
+	double pixel_fraction = ATTOSECONDS_TO_DOUBLE(pixel_time.attoseconds());
+
+	pixel_index -= 16; // take back 16 clock cycles to honor the circuitry god whose ark this is
+	if (pixel_index < 0)
+	{
+		m_last_beam = float(data);
+		m_last_hpos = 0;
+		m_last_vpos = 0;
+		m_last_fraction = 0.0;
+		return;
+	}
 
-	check_tv_interrupt();
-	update_tv_unblank();
+	const int hpos = pixel_index % SCREEN_HTOTAL;//m_screen->hpos();
+	const int vpos = pixel_index / SCREEN_HTOTAL;//m_screen->vpos();
+	const int curr_index = vpos * SCREEN_HTOTAL + hpos;
 
-	draw_scanline(&m_screen_pixbuf[old_vpos * SCREEN_HTOTAL + SCREEN_HSTART]);
+	int last_index = m_last_vpos * SCREEN_HTOTAL + m_last_hpos;
+	if (last_index != curr_index)
+	{
+		m_screen_buf[last_index] *= m_last_fraction;
+		m_screen_buf[last_index] += float(m_last_beam * (1.0 - m_last_fraction));
+		last_index++;
+		while (last_index <= curr_index)
+			m_screen_buf[last_index++] = float(m_last_beam);
+	}
 
-	m_scanline_timer->adjust(m_screen->time_until_pos((m_vpos + 1) % SCREEN_VTOTAL, 0));
+	m_last_beam = float(data);
+	m_last_hpos = hpos;
+	m_last_vpos = vpos;
+	m_last_fraction = pixel_fraction;
 }
 
-void hazl1500_state::draw_scanline(uint32_t *pix)
+WRITE8_MEMBER(hazl1500_state::refresh_address_w)
 {
-	static const uint32_t palette[4] = { 0xff000000, 0xff006000, 0xff000000, 0xff00c000 };
-
-	uint16_t ram_offset = m_refresh_address << 4;
-	uint8_t char_row = m_vpos % 11;
-	uint8_t recycle = (char_row != 10 ? 0xff : 0x00);
-	m_line_buffer_lsb->rc_w(recycle & 0xf);
-	m_line_buffer_msb->rc_w(recycle >> 4);
-
-	if (recycle == 0)
-		m_maincpu->adjust_icount(-LINE_FETCH_CYCLES);
-
-	for (uint16_t x = 0; x < 80; x++)
-	{
-		uint8_t in = 0;
-		if (!m_vblank)
-			in = m_char_ram[ram_offset + x];
-
-		m_line_buffer_lsb->in_w(in & 0xf);
-		m_line_buffer_lsb->cp_w(1);
-		m_line_buffer_lsb->cp_w(0);
-
-		m_line_buffer_msb->in_w(in >> 4);
-		m_line_buffer_msb->cp_w(1);
-		m_line_buffer_msb->cp_w(0);
-
-		const uint8_t chr = (m_line_buffer_msb->out_r() << 4) | m_line_buffer_lsb->out_r();
-		const uint16_t chr_addr = (chr & 0x7f) << 4;
-		const uint8_t gfx = m_char_rom[chr_addr | char_row];
-		const uint8_t bright = (chr & 0x80) >> 6;
-
-		*pix++ = palette[0];
-		*pix++ = palette[BIT(gfx, 6) | bright];
-		*pix++ = palette[BIT(gfx, 5) | bright];
-		*pix++ = palette[BIT(gfx, 4) | bright];
-		*pix++ = palette[BIT(gfx, 3) | bright];
-		*pix++ = palette[BIT(gfx, 2) | bright];
-		*pix++ = palette[BIT(gfx, 1) | bright];
-		*pix++ = palette[BIT(gfx, 0) | bright];
-		*pix++ = palette[0];
-	}
+	synchronize();
+	//printf("refresh: %02x, %d, %d\n", data, m_screen->hpos(), m_screen->vpos());
+	m_iowq_timer->adjust(attotime::from_hz(XTAL_18MHz/9));
+	m_cpu_iowq->write(0);
+	m_cpu_ba4->write(0);
+	m_cpu_db0->write((data >> 0) & 1);
+	m_cpu_db1->write((data >> 1) & 1);
+	m_cpu_db2->write((data >> 2) & 1);
+	m_cpu_db3->write((data >> 3) & 1);
+	m_cpu_db4->write((data >> 4) & 1);
+	m_cpu_db5->write((data >> 5) & 1);
+	m_cpu_db6->write((data >> 6) & 1);
+	m_cpu_db7->write((data >> 7) & 1);
 }
 
 static ADDRESS_MAP_START(hazl1500_mem, AS_PROGRAM, 8, hazl1500_state)
 	ADDRESS_MAP_UNMAP_HIGH
 	AM_RANGE(0x0000, 0x07ff) AM_ROM
-	AM_RANGE(0x3000, 0x377f) AM_RAM AM_SHARE(CHARRAM_TAG)
+	AM_RANGE(0x3000, 0x377f) AM_READWRITE(ram_r, ram_w)
 	AM_RANGE(0x3780, 0x37ff) AM_RAM
 ADDRESS_MAP_END
 
@@ -668,7 +681,7 @@ static const gfx_layout hazl1500_charlayout =
 };
 
 static GFXDECODE_START( hazl1500 )
-	GFXDECODE_ENTRY( "chargen", 0x0000, hazl1500_charlayout, 0, 1 )
+	GFXDECODE_ENTRY( CHAR_EPROM_TAG, 0x0000, hazl1500_charlayout, 0, 1 )
 GFXDECODE_END
 
 static MACHINE_CONFIG_START( hazl1500, hazl1500_state )
@@ -679,11 +692,14 @@ static MACHINE_CONFIG_START( hazl1500, hazl1500_state )
 	MCFG_QUANTUM_PERFECT_CPU(CPU_TAG)
 
 	/* video hardware */
-	MCFG_SCREEN_ADD_MONOCHROME(SCREEN_TAG, RASTER, rgb_t::green())
+	MCFG_SCREEN_ADD(SCREEN_TAG, RASTER)
 	MCFG_SCREEN_UPDATE_DRIVER(hazl1500_state, screen_update_hazl1500)
-	MCFG_SCREEN_RAW_PARAMS(XTAL_33_264MHz/2,
-		SCREEN_HTOTAL, SCREEN_HSTART, SCREEN_HSTART + SCREEN_HDISP,
-		SCREEN_VTOTAL, SCREEN_VSTART, SCREEN_VSTART + SCREEN_VDISP);
+	//MCFG_SCREEN_RAW_PARAMS(XTAL_33_264MHz / 2,
+	//    SCREEN_HTOTAL, SCREEN_HSTART, SCREEN_HSTART + SCREEN_HDISP,
+	//    SCREEN_VTOTAL, SCREEN_VSTART, SCREEN_VSTART + SCREEN_VDISP); // TODO: Figure out exact visibility
+	MCFG_SCREEN_RAW_PARAMS(XTAL_33_264MHz / 2,
+		SCREEN_HTOTAL, 0, SCREEN_HTOTAL,
+		SCREEN_VTOTAL, 0, SCREEN_VTOTAL);
 
 	MCFG_PALETTE_ADD_MONOCHROME("palette")
 	MCFG_GFXDECODE_ADD("gfxdecode", "palette", hazl1500)
@@ -693,74 +709,46 @@ static MACHINE_CONFIG_START( hazl1500, hazl1500_state )
 
 	MCFG_DEVICE_ADD(UART_TAG, AY51013, 0)
 
-	MCFG_TMS3409_ADD(TMS3409A_TAG)
-	MCFG_TMS3409_ADD(TMS3409B_TAG)
-
-	MCFG_CLOCK_ADD(DOTCLK_TAG, XTAL_33_264MHz/2)
-	MCFG_CLOCK_SIGNAL_HANDLER(DEVWRITELINE(DOTCLK_DISP_TAG, devcb_line_dispatch_device<2>, in_w))
-
-	MCFG_LINE_DISPATCH_ADD(DOTCLK_DISP_TAG, 2)
-	MCFG_LINE_DISPATCH_FWD_CB(0, 2, DEVWRITELINE(U81_TAG, ttl74175_device, clock_w))
-	MCFG_LINE_DISPATCH_FWD_CB(1, 2, DEVWRITELINE(U88_DIV9_TAG, ttl74161_device, clock_w))
-
-	MCFG_74161_ADD(U70_PROMLSB_TAG)
-	MCFG_7416x_QA_CB(DEVWRITELINE(U71_PROM_TAG, prom82s129_device, a0_w))
-	MCFG_7416x_QB_CB(DEVWRITELINE(U71_PROM_TAG, prom82s129_device, a1_w))
-	MCFG_7416x_QC_CB(DEVWRITELINE(U71_PROM_TAG, prom82s129_device, a2_w))
-	MCFG_7416x_QD_CB(DEVWRITELINE(U71_PROM_TAG, prom82s129_device, a3_w))
-	MCFG_7416x_TC_CB(DEVWRITELINE(U70_TC_LINE_TAG, devcb_line_dispatch_device<2>, in_w))
-
-	MCFG_LINE_DISPATCH_ADD(U70_TC_LINE_TAG, 2)
-	MCFG_LINE_DISPATCH_FWD_CB(0, 2, DEVWRITELINE(U69_PROMMSB_TAG, ttl74161_device, cet_w))
-	MCFG_LINE_DISPATCH_FWD_CB(1, 2, DEVWRITELINE(U69_PROMMSB_TAG, ttl74161_device, cep_w))
-
-	MCFG_74161_ADD(U69_PROMMSB_TAG)
-	MCFG_7416x_QA_CB(DEVWRITELINE(U71_PROM_TAG, prom82s129_device, a4_w))
-	MCFG_7416x_QB_CB(DEVWRITELINE(U71_PROM_TAG, prom82s129_device, a5_w))
-	MCFG_7416x_QC_CB(DEVWRITELINE(U71_PROM_TAG, prom82s129_device, a6_w))
-
-	//MCFG_LINE_DISPATCH_ADD(CHAR_LINE_CNT_CLK_TAG, 3)
-	//MCFG_LINE_DISPATCH_FWD_CB(0, 3, DEVWRITELINE(U85_VERT_DR_UB_TAG, ttl7473_device, clk1_w))
-	//MCFG_LINE_DISPATCH_FWD_CB(1, 3, DEVWRITELINE(U85_VERT_DR_UB_TAG, ttl7473_device, clk2_w))
-	//MCFG_LINE_DISPATCH_FWD_CB(2, 3, DEVWRITELINE(U84_DIV11_TAG, ttl74161_device, clock_w))
-
-	MCFG_7400_ADD(U83_TAG)
-	//MCFG_7400_Y1_CB(DEVWRITELINE(CHAR_LINE_CNT_CLK_TAG, devcb_line_dispatch_device<4>, in_w))
-
-	MCFG_74161_ADD(U84_DIV11_TAG)
-	MCFG_74161_ADD(U90_DIV14_TAG)
-
-	MCFG_74161_ADD(U88_DIV9_TAG)
-	MCFG_7416x_QC_CB(DEVWRITELINE(U81_TAG, ttl74175_device, d4_w))
-	MCFG_7416x_TC_CB(DEVWRITELINE(U81_TAG, ttl74175_device, d1_w))
-
-	MCFG_LINE_DISPATCH_ADD(CHAR_CTR_CLK_TAG, 2)
-	MCFG_LINE_DISPATCH_FWD_CB(0, 2, DEVWRITELINE(U70_PROMLSB_TAG, ttl74161_device, clock_w))
-	MCFG_LINE_DISPATCH_FWD_CB(1, 2, DEVWRITELINE(U69_PROMMSB_TAG, ttl74161_device, clock_w))
-
-	MCFG_74175_ADD(U58_TAG)
-	MCFG_74175_ADD(U68_TAG)
-	MCFG_74175_ADD(U81_TAG)
-	MCFG_74175_Q1_CB(DEVWRITELINE(U81_TAG, ttl74175_device, d2_w))
-	MCFG_74175_NOT_Q2_CB(DEVWRITELINE(CHAR_CTR_CLK_TAG, devcb_line_dispatch_device<2>, in_w))
-
-	MCFG_DM9334_ADD(U72_PROMDEC_TAG)
-	MCFG_DM9334_Q4_CB(DEVWRITELINE(U83_TAG, ttl7400_device, b1_w))
-
-	MCFG_82S129_ADD(U71_PROM_TAG)
-	MCFG_82S129_O1_CB(DEVWRITELINE(U72_PROMDEC_TAG, dm9334_device, a0_w))
-	MCFG_82S129_O2_CB(DEVWRITELINE(U72_PROMDEC_TAG, dm9334_device, a1_w))
-	MCFG_82S129_O3_CB(DEVWRITELINE(U72_PROMDEC_TAG, dm9334_device, a2_w))
-	MCFG_82S129_O4_CB(DEVWRITELINE(U72_PROMDEC_TAG, dm9334_device, d_w))
-
-	MCFG_7404_ADD(U61_TAG)
-	MCFG_7404_ADD(U87_TAG)
-	MCFG_7404_ADD(U59_TAG)
-	MCFG_7404_Y5_CB(DEVWRITELINE(VID_PROM_ADDR_RESET_TAG, devcb_line_dispatch_device<2>, in_w))
-
-	MCFG_LINE_DISPATCH_ADD(VID_PROM_ADDR_RESET_TAG, 2)
-	MCFG_LINE_DISPATCH_FWD_CB(0, 2, DEVWRITELINE(U70_PROMLSB_TAG, ttl74161_device, pe_w))
-	MCFG_LINE_DISPATCH_FWD_CB(1, 2, DEVWRITELINE(U69_PROMMSB_TAG, ttl74161_device, pe_w))
+	MCFG_DEVICE_ADD(NETLIST_TAG, NETLIST_CPU, VIDEOBRD_CLOCK)
+	MCFG_NETLIST_SETUP(hazelvid)
+
+	MCFG_NETLIST_ROM_REGION(NETLIST_TAG, VIDEO_PROM_TAG, VIDEO_PROM_TAG, VIDEO_PROM_TAG)
+	MCFG_NETLIST_ROM_REGION(NETLIST_TAG, CHAR_EPROM_TAG, CHAR_EPROM_TAG, CHAR_EPROM_TAG)
+
+	// First 1K
+	MCFG_NETLIST_RAM_POINTER(NETLIST_TAG, "u22", "u22")
+	MCFG_NETLIST_RAM_POINTER(NETLIST_TAG, "u23", "u23")
+	MCFG_NETLIST_RAM_POINTER(NETLIST_TAG, "u24", "u24")
+	MCFG_NETLIST_RAM_POINTER(NETLIST_TAG, "u25", "u25")
+	MCFG_NETLIST_RAM_POINTER(NETLIST_TAG, "u26", "u26")
+	MCFG_NETLIST_RAM_POINTER(NETLIST_TAG, "u27", "u27")
+	MCFG_NETLIST_RAM_POINTER(NETLIST_TAG, "u28", "u28")
+	MCFG_NETLIST_RAM_POINTER(NETLIST_TAG, "u29", "u29")
+
+	// Second 1K
+	MCFG_NETLIST_RAM_POINTER(NETLIST_TAG, "u9",  "u9")
+	MCFG_NETLIST_RAM_POINTER(NETLIST_TAG, "u10", "u10")
+	MCFG_NETLIST_RAM_POINTER(NETLIST_TAG, "u11", "u11")
+	MCFG_NETLIST_RAM_POINTER(NETLIST_TAG, "u12", "u12")
+	MCFG_NETLIST_RAM_POINTER(NETLIST_TAG, "u13", "u13")
+	MCFG_NETLIST_RAM_POINTER(NETLIST_TAG, "u14", "u14")
+	MCFG_NETLIST_RAM_POINTER(NETLIST_TAG, "u15", "u15")
+	MCFG_NETLIST_RAM_POINTER(NETLIST_TAG, "u16", "u16")
+
+	MCFG_NETLIST_LOGIC_INPUT(NETLIST_TAG, "cpu_iowq", "cpu_iowq.IN", 0)
+	MCFG_NETLIST_LOGIC_INPUT(NETLIST_TAG, "cpu_ba4", "cpu_ba4.IN", 0)
+	MCFG_NETLIST_LOGIC_INPUT(NETLIST_TAG, "cpu_db0", "cpu_db0.IN", 0)
+	MCFG_NETLIST_LOGIC_INPUT(NETLIST_TAG, "cpu_db1", "cpu_db1.IN", 0)
+	MCFG_NETLIST_LOGIC_INPUT(NETLIST_TAG, "cpu_db2", "cpu_db2.IN", 0)
+	MCFG_NETLIST_LOGIC_INPUT(NETLIST_TAG, "cpu_db3", "cpu_db3.IN", 0)
+	MCFG_NETLIST_LOGIC_INPUT(NETLIST_TAG, "cpu_db4", "cpu_db4.IN", 0)
+	MCFG_NETLIST_LOGIC_INPUT(NETLIST_TAG, "cpu_db5", "cpu_db5.IN", 0)
+	MCFG_NETLIST_LOGIC_INPUT(NETLIST_TAG, "cpu_db6", "cpu_db6.IN", 0)
+	MCFG_NETLIST_LOGIC_INPUT(NETLIST_TAG, "cpu_db7", "cpu_db7.IN", 0)
+
+	MCFG_NETLIST_ANALOG_OUTPUT(NETLIST_TAG, "video_out", "video_out", hazl1500_state, video_out_cb, "")
+	MCFG_NETLIST_ANALOG_OUTPUT(NETLIST_TAG, "vblank", "vblank", hazl1500_state, vblank_cb, "")
+	MCFG_NETLIST_ANALOG_OUTPUT(NETLIST_TAG, "tvinterq", "tvinterq", hazl1500_state, tvinterq_cb, "")
 
 	/* keyboard controller */
 	MCFG_DEVICE_ADD(KBDC_TAG, AY3600, 0)
@@ -780,16 +768,18 @@ MACHINE_CONFIG_END
 
 
 ROM_START( hazl1500 )
+	ROM_REGION( 0x10000, NETLIST_TAG, ROMREGION_ERASE00 )
+
 	ROM_REGION( 0x10000, CPU_TAG, ROMREGION_ERASEFF )
 	ROM_LOAD( "h15s-00I-10-3.bin", 0x0000, 0x0800, CRC(a2015f72) SHA1(357cde517c3dcf693de580881add058c7b26dfaa))
 
-	ROM_REGION( 0x800, CHARROM_TAG, ROMREGION_ERASEFF )
+	ROM_REGION( 0x800, CHAR_EPROM_TAG, ROMREGION_ERASEFF )
 	ROM_LOAD( "u83_chr.bin", 0x0000, 0x0800, CRC(e0c6b734) SHA1(7c42947235c66c41059fd4384e09f4f3a17c9857))
 
 	ROM_REGION( 0x100, BAUD_PROM_TAG, ROMREGION_ERASEFF )
 	ROM_LOAD( "u43_702129_82s129.bin", 0x0000, 0x0100, CRC(b35aea2b) SHA1(4702620cdef72b32a397580c22b75df36e24ac74))
 
-	ROM_REGION( 0x100, U71_PROM_TAG, ROMREGION_ERASEFF )
+	ROM_REGION( 0x100, VIDEO_PROM_TAG, ROMREGION_ERASEFF )
 	ROM_LOAD( "u90_702128_82s129.bin", 0x0000, 0x0100, CRC(277bc424) SHA1(528a0de3b54d159bc14411961961706bf9ec41bf))
 ROM_END
 
diff --git a/src/mame/drivers/hh_amis2k.cpp b/src/mame/drivers/hh_amis2k.cpp
index 1e20674..92ddc83 100644
--- a/src/mame/drivers/hh_amis2k.cpp
+++ b/src/mame/drivers/hh_amis2k.cpp
@@ -337,7 +337,7 @@ MACHINE_CONFIG_END
 
 ROM_START( wildfire )
 	ROM_REGION( 0x0800, "maincpu", ROMREGION_ERASE00 )
-	ROM_LOAD( "us4341385", 0x0000, 0x0400, CRC(84ac0f1f) SHA1(1e00ddd402acfc2cc267c34eed4b89d863e2144f) ) // from patent US4334679, data should be correct (it included checksums)
+	ROM_LOAD( "us4341385", 0x0000, 0x0400, CRC(84ac0f1f) SHA1(1e00ddd402acfc2cc267c34eed4b89d863e2144f) ) // from patent US4334679, data should be correct (it included checksums). 1st half was dumped/verfied too.
 	ROM_CONTINUE(          0x0600, 0x0200 )
 ROM_END
 
diff --git a/src/mame/drivers/hh_cop400.cpp b/src/mame/drivers/hh_cop400.cpp
index 30b49d3..28be622 100644
--- a/src/mame/drivers/hh_cop400.cpp
+++ b/src/mame/drivers/hh_cop400.cpp
@@ -6,9 +6,7 @@
   mostly LED electronic games/toys.
 
   TODO:
-  - non-working games are due to MCU emulation bugs?
-  - better not start on visually dumped games before other games are working
-    (due to possible dump errors, hard to distinguish between that or MCU bug)
+  - why does h2hbaskb need a workaround on writing L pins?
 
 ***************************************************************************/
 
@@ -25,6 +23,7 @@
 #include "funrlgl.lh"
 #include "h2hbaskb.lh"
 #include "lightfgt.lh" // clickable
+#include "qkracer.lh"
 
 //#include "hh_cop400_test.lh" // common test-layout - use external artwork
 
@@ -280,7 +279,6 @@ WRITE8_MEMBER(ctstein_state::write_l)
 {
 	// L0-L3: button lamps (strobed)
 	display_matrix(4, 1, data & 0xf, 1);
-	display_matrix(4, 1, 0, 0);
 }
 
 READ8_MEMBER(ctstein_state::read_l)
@@ -497,8 +495,7 @@ public:
 void einvaderc_state::prepare_display()
 {
 	// D0-D2 are 7segs
-	for (int y = 0; y < 3; y++)
-		m_display_segmask[y] = 0x7f;
+	set_display_segmask(7, 0x7f);
 
 	// update display
 	uint8_t l = BITSWAP8(m_l,7,6,0,1,2,3,4,5);
@@ -612,7 +609,7 @@ WRITE8_MEMBER(funjacks_state::write_d)
 {
 	// D: led grid + input mux
 	m_inp_mux = data;
-	m_d = data ^ 0xf;
+	m_d = ~data & 0xf;
 	display_matrix(2, 4, m_l, m_d);
 }
 
@@ -633,7 +630,7 @@ WRITE8_MEMBER(funjacks_state::write_g)
 READ8_MEMBER(funjacks_state::read_l)
 {
 	// L4,L5: multiplexed inputs
-	return read_inputs(3) & 0x30;
+	return (read_inputs(3) & 0x30) | m_l;
 }
 
 READ8_MEMBER(funjacks_state::read_g)
@@ -648,16 +645,16 @@ READ8_MEMBER(funjacks_state::read_g)
 
 static INPUT_PORTS_START( funjacks )
 	PORT_START("IN.0") // D0 port G
-	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON2 )
-	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON3 )
+	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON3 )
+	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 )
 
 	PORT_START("IN.1") // D1 port G
-	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON5 )
-	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON4 )
+	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON4 )
+	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON5 )
 
 	PORT_START("IN.2") // D2 port G
-	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) // positioned at 1 o'clock on panel, increment clockwise
-	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON6 )
+	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON6 )
+	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) // positioned at 1 o'clock on panel, increment clockwise
 
 	PORT_START("IN.3") // port G
 	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
@@ -671,8 +668,8 @@ INPUT_PORTS_END
 static MACHINE_CONFIG_START( funjacks, funjacks_state )
 
 	/* basic machine hardware */
-	MCFG_CPU_ADD("maincpu", COP410, 2000000) // approximation - RC osc. R=47K, C=56pf
-	MCFG_COP400_CONFIG(COP400_CKI_DIVISOR_16, COP400_CKO_OSCILLATOR_OUTPUT, true) // guessed
+	MCFG_CPU_ADD("maincpu", COP410, 1000000) // approximation - RC osc. R=47K, C=56pf
+	MCFG_COP400_CONFIG(COP400_CKI_DIVISOR_8, COP400_CKO_OSCILLATOR_OUTPUT, false) // guessed
 	MCFG_COP400_WRITE_D_CB(WRITE8(funjacks_state, write_d))
 	MCFG_COP400_WRITE_L_CB(WRITE8(funjacks_state, write_l))
 	MCFG_COP400_WRITE_G_CB(WRITE8(funjacks_state, write_g))
@@ -718,6 +715,7 @@ public:
 	DECLARE_WRITE8_MEMBER(write_d);
 	DECLARE_WRITE8_MEMBER(write_l);
 	DECLARE_WRITE8_MEMBER(write_g);
+	DECLARE_READ8_MEMBER(read_l_tristate) { return 0xff; }
 
 	DECLARE_INPUT_CHANGED_MEMBER(reset_button);
 };
@@ -727,7 +725,7 @@ public:
 WRITE8_MEMBER(funrlgl_state::write_d)
 {
 	// D: led grid
-	m_d = data ^ 0xf;
+	m_d = ~data & 0xf;
 	display_matrix(4, 4, m_l, m_d);
 }
 
@@ -735,7 +733,7 @@ WRITE8_MEMBER(funrlgl_state::write_l)
 {
 	// L0-L3: led state
 	// L4-L7: N/C
-	m_l = data & 0xf;
+	m_l = ~data & 0xf;
 	display_matrix(4, 4, m_l, m_d);
 }
 
@@ -771,10 +769,11 @@ INPUT_CHANGED_MEMBER(funrlgl_state::reset_button)
 static MACHINE_CONFIG_START( funrlgl, funrlgl_state )
 
 	/* basic machine hardware */
-	MCFG_CPU_ADD("maincpu", COP410, 2000000) // approximation - RC osc. R=51K, C=91pf
-	MCFG_COP400_CONFIG(COP400_CKI_DIVISOR_16, COP400_CKO_OSCILLATOR_OUTPUT, true) // guessed
+	MCFG_CPU_ADD("maincpu", COP410, 1000000) // approximation - RC osc. R=51K, C=91pf
+	MCFG_COP400_CONFIG(COP400_CKI_DIVISOR_8, COP400_CKO_OSCILLATOR_OUTPUT, true) // guessed
 	MCFG_COP400_WRITE_D_CB(WRITE8(funrlgl_state, write_d))
 	MCFG_COP400_WRITE_L_CB(WRITE8(funrlgl_state, write_l))
+	MCFG_COP400_READ_L_TRISTATE_CB(READ8(funrlgl_state, read_l_tristate))
 	MCFG_COP400_WRITE_G_CB(WRITE8(funrlgl_state, write_g))
 	MCFG_COP400_READ_G_CB(IOPORT("IN.0"))
 
@@ -843,7 +842,7 @@ static MACHINE_CONFIG_START( plus1, plus1_state )
 
 	/* basic machine hardware */
 	MCFG_CPU_ADD("maincpu", COP410, 1000000) // approximation - RC osc. R=51K, C=100pf
-	MCFG_COP400_CONFIG(COP400_CKI_DIVISOR_16, COP400_CKO_OSCILLATOR_OUTPUT, true) // guessed
+	MCFG_COP400_CONFIG(COP400_CKI_DIVISOR_16, COP400_CKO_OSCILLATOR_OUTPUT, false) // guessed
 	MCFG_COP400_WRITE_D_CB(WRITE8(plus1_state, write_d))
 	MCFG_COP400_READ_G_CB(IOPORT("IN.0"))
 	MCFG_COP400_READ_L_CB(IOPORT("IN.1"))
@@ -1150,6 +1149,133 @@ MACHINE_CONFIG_END
 
 /***************************************************************************
 
+  National Semiconductor QuizKid Racer (COP420 version)
+  * COP420 MCU label COP420-NPG/N
+  * 8-digit 7seg led display(1 custom digit), 1 green led, no sound
+
+  This is the COP420 version, the first release was on a MM5799 MCU.
+
+***************************************************************************/
+
+class qkracer_state : public hh_cop400_state
+{
+public:
+	qkracer_state(const machine_config &mconfig, device_type type, const char *tag)
+		: hh_cop400_state(mconfig, type, tag)
+	{ }
+
+	void prepare_display();
+	DECLARE_WRITE8_MEMBER(write_d);
+	DECLARE_WRITE8_MEMBER(write_g);
+	DECLARE_WRITE8_MEMBER(write_l);
+	DECLARE_READ8_MEMBER(read_in);
+	DECLARE_WRITE_LINE_MEMBER(write_sk);
+};
+
+// handlers
+
+void qkracer_state::prepare_display()
+{
+	set_display_segmask(0xdf, 0x7f);
+	set_display_segmask(0x20, 0x41); // equals sign
+
+	display_matrix(7, 9, m_l, ~(m_d | m_g << 4 | m_sk << 8));
+}
+
+WRITE8_MEMBER(qkracer_state::write_d)
+{
+	// D: select digit, D3: input mux high bit
+	m_inp_mux = (m_inp_mux & 0xf) | (data << 1 & 0x10);
+	m_d = data & 0xf;
+	prepare_display();
+}
+
+WRITE8_MEMBER(qkracer_state::write_g)
+{
+	// G: select digit, input mux
+	m_inp_mux = (m_inp_mux & 0x10) | (data & 0xf);
+	m_g = data & 0xf;
+	prepare_display();
+}
+
+WRITE8_MEMBER(qkracer_state::write_l)
+{
+	// L0-L6: digit segment data
+	m_l = data & 0x7f;
+	prepare_display();
+}
+
+READ8_MEMBER(qkracer_state::read_in)
+{
+	// IN: multiplexed inputs
+	return read_inputs(5) & 0xf;
+}
+
+WRITE_LINE_MEMBER(qkracer_state::write_sk)
+{
+	// SK: green led
+	m_sk = state;
+	prepare_display();
+}
+
+
+// config
+
+static INPUT_PORTS_START( qkracer )
+	PORT_START("IN.0") // G0 port IN
+	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_7) PORT_CODE(KEYCODE_7_PAD) PORT_NAME("7")
+	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_8) PORT_CODE(KEYCODE_8_PAD) PORT_NAME("8")
+	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_9) PORT_CODE(KEYCODE_9_PAD) PORT_NAME("9")
+	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_SLASH_PAD) PORT_NAME(UTF8_DIVIDE)
+
+	PORT_START("IN.1") // G1 port IN
+	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_4) PORT_CODE(KEYCODE_4_PAD) PORT_NAME("4")
+	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_5) PORT_CODE(KEYCODE_5_PAD) PORT_NAME("5")
+	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_6) PORT_CODE(KEYCODE_6_PAD) PORT_NAME("6")
+	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_ASTERISK) PORT_NAME(UTF8_MULTIPLY)
+
+	PORT_START("IN.2") // G2 port IN
+	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_1) PORT_CODE(KEYCODE_1_PAD) PORT_NAME("1")
+	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_2) PORT_CODE(KEYCODE_2_PAD) PORT_NAME("2")
+	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_3) PORT_CODE(KEYCODE_3_PAD) PORT_NAME("3")
+	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_MINUS_PAD) PORT_NAME("-")
+
+	PORT_START("IN.3") // G3 port IN
+	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_MINUS) PORT_NAME("Slow")
+	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_EQUALS) PORT_NAME("Fast")
+	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_0) PORT_CODE(KEYCODE_0_PAD) PORT_NAME("0")
+	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_PLUS_PAD) PORT_NAME("+")
+
+	PORT_START("IN.4") // D3 port IN
+	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_Q) PORT_NAME("Amateur")
+	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_W) PORT_NAME("Pro")
+	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_E) PORT_NAME("Complex")
+	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_R) PORT_NAME("Tables")
+INPUT_PORTS_END
+
+static MACHINE_CONFIG_START( qkracer, qkracer_state )
+
+	/* basic machine hardware */
+	MCFG_CPU_ADD("maincpu", COP420, 1000000) // approximation - RC osc. R=47K, C=100pf
+	MCFG_COP400_CONFIG(COP400_CKI_DIVISOR_32, COP400_CKO_OSCILLATOR_OUTPUT, false) // guessed
+	MCFG_COP400_WRITE_D_CB(WRITE8(qkracer_state, write_d))
+	MCFG_COP400_WRITE_G_CB(WRITE8(qkracer_state, write_g))
+	MCFG_COP400_WRITE_L_CB(WRITE8(qkracer_state, write_l))
+	MCFG_COP400_READ_IN_CB(READ8(qkracer_state, read_in))
+	MCFG_COP400_WRITE_SK_CB(WRITELINE(qkracer_state, write_sk))
+
+	MCFG_TIMER_DRIVER_ADD_PERIODIC("display_decay", hh_cop400_state, display_decay_tick, attotime::from_msec(1))
+	MCFG_DEFAULT_LAYOUT(layout_qkracer)
+
+	/* no sound! */
+MACHINE_CONFIG_END
+
+
+
+
+
+/***************************************************************************
+
   Game driver(s)
 
 ***************************************************************************/
@@ -1202,20 +1328,28 @@ ROM_START( bship82 )
 ROM_END
 
 
+ROM_START( qkracer )
+	ROM_REGION( 0x0400, "maincpu", 0 )
+	ROM_LOAD( "cop420-npg_n", 0x0000, 0x0400, CRC(17f8e538) SHA1(23d1a1819e6ba552d8da83da2948af1cf5b13d5b) )
+ROM_END
+
+
 
 /*    YEAR  NAME       PARENT COMPAT MACHINE   INPUT      INIT              COMPANY, FULLNAME, FLAGS */
 CONS( 1979, ctstein,   0,        0, ctstein,   ctstein,   driver_device, 0, "Castle Toy", "Einstein (Castle Toy)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK )
 
 CONS( 1980, h2hbaskb,  0,        0, h2hbaskb,  h2hbaskb,  driver_device, 0, "Coleco", "Head to Head Basketball/Hockey/Soccer (COP420L version)", MACHINE_SUPPORTS_SAVE )
 
-CONS( 1981, einvaderc, einvader, 0, einvaderc, einvaderc, driver_device, 0, "Entex", "Space Invader (Entex, COP444L version)", MACHINE_SUPPORTS_SAVE | MACHINE_REQUIRES_ARTWORK | MACHINE_NOT_WORKING )
+CONS( 1981, einvaderc, einvader, 0, einvaderc, einvaderc, driver_device, 0, "Entex", "Space Invader (Entex, COP444L version)", MACHINE_SUPPORTS_SAVE | MACHINE_REQUIRES_ARTWORK )
 
-CONS( 1979, funjacks,  0,        0, funjacks,  funjacks,  driver_device, 0, "Mattel", "Funtronics Jacks", MACHINE_SUPPORTS_SAVE | MACHINE_NOT_WORKING )
-CONS( 1979, funrlgl,   0,        0, funrlgl,   funrlgl,   driver_device, 0, "Mattel", "Funtronics Red Light Green Light", MACHINE_SUPPORTS_SAVE | MACHINE_NOT_WORKING )
+CONS( 1979, funjacks,  0,        0, funjacks,  funjacks,  driver_device, 0, "Mattel", "Funtronics Jacks", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK )
+CONS( 1979, funrlgl,   0,        0, funrlgl,   funrlgl,   driver_device, 0, "Mattel", "Funtronics Red Light Green Light", MACHINE_SUPPORTS_SAVE )
 
 CONS( 1980, plus1,     0,        0, plus1,     plus1,     driver_device, 0, "Milton Bradley", "Plus One", MACHINE_SUPPORTS_SAVE | MACHINE_NOT_WORKING ) // ***
 CONS( 1981, lightfgt,  0,        0, lightfgt,  lightfgt,  driver_device, 0, "Milton Bradley", "Lightfight", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK )
 CONS( 1982, bship82,   bship,    0, bship82,   bship82,   driver_device, 0, "Milton Bradley", "Electronic Battleship (1982 version)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK ) // ***
 
+CONS( 1978, qkracer,   0,        0, qkracer,   qkracer,   driver_device, 0, "National Semiconductor", "QuizKid Racer (COP420 version)", MACHINE_SUPPORTS_SAVE | MACHINE_NO_SOUND_HW )
+
 // ***: As far as MAME is concerned, the game is emulated fine. But for it to be playable, it requires interaction
 // with other, unemulatable, things eg. game board/pieces, playing cards, pen & paper, etc.
diff --git a/src/mame/drivers/hikaru.cpp b/src/mame/drivers/hikaru.cpp
index d3f4a0f..ed2ef61 100644
--- a/src/mame/drivers/hikaru.cpp
+++ b/src/mame/drivers/hikaru.cpp
@@ -767,7 +767,7 @@ ROM_START( sgnascar )
 	ROM_LOAD32_WORD( "mpr-23480.ic33", 0xe000000, 0x1000000, CRC(f517b8b3) SHA1(c04740adb612473c4c9f8186e7e93d2f73d1bb1a) )
 	ROM_LOAD32_WORD( "mpr-23484.ic34", 0xe000002, 0x1000000, CRC(2ebe1aa1) SHA1(16b39f7422da1a334dde27169c2949e1d95bddb3) )
 
-	// 317-0283-COM Actel A54SX32
+	// 834-14125 317-0283-COM Actel A54SX32
 	// ID 0x4252
 	ROM_PARAMETER( ":rom_board:key", "56dedf33" )
 ROM_END
@@ -799,7 +799,7 @@ ROM_START( sgnascaro )
 	ROM_LOAD32_WORD( "mpr-23480.ic33", 0xe000000, 0x1000000, CRC(f517b8b3) SHA1(c04740adb612473c4c9f8186e7e93d2f73d1bb1a) )
 	ROM_LOAD32_WORD( "mpr-23484.ic34", 0xe000002, 0x1000000, CRC(2ebe1aa1) SHA1(16b39f7422da1a334dde27169c2949e1d95bddb3) )
 
-	// 317-0283-COM Actel A54SX32
+	// 834-14125 317-0283-COM Actel A54SX32
 	// ID 0x4252
 	ROM_PARAMETER( ":rom_board:key", "56dedf33" )
 ROM_END
diff --git a/src/mame/drivers/homedata.cpp b/src/mame/drivers/homedata.cpp
index 2ba700e..7e1d20f 100644
--- a/src/mame/drivers/homedata.cpp
+++ b/src/mame/drivers/homedata.cpp
@@ -1625,6 +1625,31 @@ ROM_START( mjclinic )
 	ROM_LOAD( "x80_a08.13a", 0x0000, 0x20000, CRC(174e8ec0) SHA1(a5075fe4bba9403ef9e0636d5f3f66aad8b2bc54) )
 ROM_END
 
+ROM_START( mjclinica )
+	ROM_REGION( 0x010000, "maincpu", 0 ) /* 6809 Code */
+	ROM_LOAD( "x80_f01.6g", 0x08000, 0x8000, CRC(cd814ec0) SHA1(55b2c9519fc98f71a2731c3851ce56ee8e57bd66) ) // labeled f01 instead of g01. Earlier version?
+
+	ROM_REGION( 0x30000, "audiocpu", 0 )    /* Z80 code */
+	ROM_LOAD( "x80_a10.11k", 0x00000, 0x20000, CRC(afedbadf) SHA1(e2f101b59c0d23f9dc9b057c41d496fc3223cbb8) )
+	ROM_RELOAD(              0x10000, 0x20000 )
+
+	ROM_REGION( 0x20000, "gfx1", 0 )
+	ROM_LOAD( "x80_a03.1g", 0, 0x20000, CRC(34b63c89) SHA1(98383ce8e464ecc53677c060338cc03aa6238a0e) )
+
+	ROM_REGION( 0x80000, "gfx2", 0 )
+	ROM_LOAD( "x80_a040.bin", 0x00000, 0x20000, CRC(6f18a8cf) SHA1(af8de2bd8b2157ceaa8192ead51ac4489c464ab2) )
+	ROM_LOAD( "x80_a050.bin", 0x20000, 0x20000, CRC(6b1ec3a9) SHA1(dc7a857bb102325ebf2522369a231260c2e02c89) )
+	ROM_LOAD( "x80_a041.bin", 0x40000, 0x20000, CRC(f70bb001) SHA1(3b29bb0bd155e97d3ccc72a8a07046c676c8452d) )
+	ROM_LOAD( "x80_a051.bin", 0x60000, 0x20000, CRC(c7469cb8) SHA1(bcf7021667e943991865fdbc9620f00b09e1db3e) )
+
+	ROM_REGION( 0x010000, "proms", 0 )  /* static palette */
+	ROM_LOAD16_BYTE( "x80_a06.1l", 0x00000, 0x8000, CRC(c1f9b2fb) SHA1(abe17e2b3b880f91564e32c246116c33e2884889) )
+	ROM_LOAD16_BYTE( "x80_a07.1m", 0x00001, 0x8000, CRC(e3120152) SHA1(b4a778a9b91e204e2c068dff9a40bd29eccf04a5) )
+
+	ROM_REGION( 0x20000, "user1", 0 ) /* blitter data */
+	ROM_LOAD( "x80_a08.13a", 0x0000, 0x20000, CRC(174e8ec0) SHA1(a5075fe4bba9403ef9e0636d5f3f66aad8b2bc54) )
+ROM_END
+
 ROM_START( mrokumei )
 	ROM_REGION( 0x010000, "maincpu", 0 ) /* 6809 Code */
 	ROM_LOAD( "m81d01.bin", 0x08000, 0x8000, CRC(6f81a78a) SHA1(5e16327b04b065ed4e39a147b18711902dba6384) )
@@ -2038,24 +2063,25 @@ DRIVER_INIT_MEMBER(homedata_state,mirderby)
 }
 
 
-GAME( 1987, hourouki, 0, mrokumei, mjhokite, driver_device,  0,          ROT0, "Home Data", "Mahjong Hourouki Part 1 - Seisyun Hen (Japan)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
-GAME( 1987, mhgaiden, 0, mrokumei, mjhokite, driver_device,  0,          ROT0, "Home Data", "Mahjong Hourouki Gaiden (Japan)", MACHINE_SUPPORTS_SAVE )
-GAME( 1988, mjhokite, 0, mrokumei, mjhokite, driver_device,  0,          ROT0, "Home Data", "Mahjong Hourouki Okite (Japan)", MACHINE_SUPPORTS_SAVE )
-GAME( 1988, mjclinic, 0, mrokumei, mjhokite, driver_device,  0,          ROT0, "Home Data", "Mahjong Clinic (Japan)", MACHINE_SUPPORTS_SAVE )
-GAME( 1988, mrokumei, 0, mrokumei, mjhokite, driver_device,  0,          ROT0, "Home Data", "Mahjong Rokumeikan (Japan)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
+GAME( 1987, hourouki,  0,        mrokumei, mjhokite, driver_device,  0,          ROT0, "Home Data", "Mahjong Hourouki Part 1 - Seisyun Hen (Japan)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
+GAME( 1987, mhgaiden,  0,        mrokumei, mjhokite, driver_device,  0,          ROT0, "Home Data", "Mahjong Hourouki Gaiden (Japan)", MACHINE_SUPPORTS_SAVE )
+GAME( 1988, mjhokite,  0,        mrokumei, mjhokite, driver_device,  0,          ROT0, "Home Data", "Mahjong Hourouki Okite (Japan)", MACHINE_SUPPORTS_SAVE )
+GAME( 1988, mjclinic,  0,        mrokumei, mjhokite, driver_device,  0,          ROT0, "Home Data", "Mahjong Clinic (Japan, set 1)", MACHINE_SUPPORTS_SAVE )
+GAME( 1988, mjclinica, mjclinic, mrokumei, mjhokite, driver_device,  0,          ROT0, "Home Data", "Mahjong Clinic (Japan, set 2)", MACHINE_SUPPORTS_SAVE )
+GAME( 1988, mrokumei,  0,        mrokumei, mjhokite, driver_device,  0,          ROT0, "Home Data", "Mahjong Rokumeikan (Japan)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
 
-GAME( 1988, reikaids, 0, reikaids, reikaids, homedata_state, reikaids,   ROT0, "Home Data", "Reikai Doushi (Japan)", MACHINE_SUPPORTS_SAVE )
-GAME( 1991, battlcry, 0, reikaids, battlcry, homedata_state, battlcry,   ROT0, "Home Data", "Battlecry", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
-GAME( 1989, mjkojink, 0, pteacher, pteacher, driver_device,  0,          ROT0, "Home Data", "Mahjong Kojinkyouju (Private Teacher) (Japan)", MACHINE_SUPPORTS_SAVE )
-GAME( 1988, mjjoship, 0, pteacher, mjjoship, driver_device,  0,          ROT0, "Home Data", "Mahjong Joshi Pro-wres -Give up 5 byou mae- (Japan)", MACHINE_SUPPORTS_SAVE )
-GAME( 1989, vitaminc, 0, pteacher, pteacher, driver_device,  0,          ROT0, "Home Data", "Mahjong Vitamin C (Japan)", MACHINE_SUPPORTS_SAVE )
-GAME( 1989, mjyougo,  0, pteacher, pteacher, driver_device,  0,          ROT0, "Home Data", "Mahjong-yougo no Kisotairyoku (Japan)", MACHINE_SUPPORTS_SAVE )
-GAME( 1991, mjkinjas, 0, mjkinjas, pteacher, driver_device,  0,          ROT0, "Home Data", "Mahjong Kinjirareta Asobi (Japan)", MACHINE_SUPPORTS_SAVE )
-GAME( 1992?,jogakuen, 0, pteacher, jogakuen, homedata_state, jogakuen,   ROT0, "Windom",    "Mahjong Jogakuen (Japan)", MACHINE_SUPPORTS_SAVE )
+GAME( 1988, reikaids,  0,        reikaids, reikaids, homedata_state, reikaids,   ROT0, "Home Data", "Reikai Doushi (Japan)", MACHINE_SUPPORTS_SAVE )
+GAME( 1991, battlcry,  0,        reikaids, battlcry, homedata_state, battlcry,   ROT0, "Home Data", "Battlecry", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
+GAME( 1989, mjkojink,  0,        pteacher, pteacher, driver_device,  0,          ROT0, "Home Data", "Mahjong Kojinkyouju (Private Teacher) (Japan)", MACHINE_SUPPORTS_SAVE )
+GAME( 1988, mjjoship,  0,        pteacher, mjjoship, driver_device,  0,          ROT0, "Home Data", "Mahjong Joshi Pro-wres -Give up 5 byou mae- (Japan)", MACHINE_SUPPORTS_SAVE )
+GAME( 1989, vitaminc,  0,        pteacher, pteacher, driver_device,  0,          ROT0, "Home Data", "Mahjong Vitamin C (Japan)", MACHINE_SUPPORTS_SAVE )
+GAME( 1989, mjyougo,   0,        pteacher, pteacher, driver_device,  0,          ROT0, "Home Data", "Mahjong-yougo no Kisotairyoku (Japan)", MACHINE_SUPPORTS_SAVE )
+GAME( 1991, mjkinjas,  0,        mjkinjas, pteacher, driver_device,  0,          ROT0, "Home Data", "Mahjong Kinjirareta Asobi (Japan)", MACHINE_SUPPORTS_SAVE )
+GAME( 1992?,jogakuen,  0,        pteacher, jogakuen, homedata_state, jogakuen,   ROT0, "Windom",    "Mahjong Jogakuen (Japan)", MACHINE_SUPPORTS_SAVE )
 
-GAME( 1990, lemnangl, 0, lemnangl, pteacher, driver_device,  0,          ROT0, "Home Data", "Mahjong Lemon Angel (Japan)", MACHINE_SUPPORTS_SAVE )
-GAME( 1991, mjprivat, 0, lemnangl, pteacher, driver_device,  0,          ROT0, "Matoba",    "Mahjong Private (Japan)", MACHINE_SUPPORTS_SAVE )
+GAME( 1990, lemnangl,  0,        lemnangl, pteacher, driver_device,  0,          ROT0, "Home Data", "Mahjong Lemon Angel (Japan)", MACHINE_SUPPORTS_SAVE )
+GAME( 1991, mjprivat,  0,        lemnangl, pteacher, driver_device,  0,          ROT0, "Matoba",    "Mahjong Private (Japan)", MACHINE_SUPPORTS_SAVE )
 
-GAME( 1991?,mjikaga,  0, lemnangl, mjikaga,  homedata_state, mjikaga,    ROT0, "Mitchell",  "Mahjong Ikaga Desu ka (Japan)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
+GAME( 1991?,mjikaga,   0,        lemnangl, mjikaga,  homedata_state, mjikaga,    ROT0, "Mitchell",  "Mahjong Ikaga Desu ka (Japan)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
 
-GAME( 1988, mirderby, 0, mirderby, mirderby, homedata_state, mirderby,   ROT0, "Home Data?", "Miracle Derby - Ascot", MACHINE_NO_SOUND|MACHINE_NOT_WORKING )
+GAME( 1988, mirderby,  0,        mirderby, mirderby, homedata_state, mirderby,   ROT0, "Home Data?", "Miracle Derby - Ascot", MACHINE_NO_SOUND|MACHINE_NOT_WORKING )
diff --git a/src/mame/drivers/homerun.cpp b/src/mame/drivers/homerun.cpp
index 779a01e..7417c51 100644
--- a/src/mame/drivers/homerun.cpp
+++ b/src/mame/drivers/homerun.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /*
  Moero!! Pro Yakyuu Homerun Kyousou - (c) 1988 Jaleco
diff --git a/src/mame/drivers/hp9k_3xx.cpp b/src/mame/drivers/hp9k_3xx.cpp
index 045cd2a..e43b4cf 100644
--- a/src/mame/drivers/hp9k_3xx.cpp
+++ b/src/mame/drivers/hp9k_3xx.cpp
@@ -291,8 +291,7 @@ static MACHINE_CONFIG_START( hp9k310, hp9k3xx_state )
 	MCFG_CPU_ADD(MAINCPU_TAG, M68010, 10000000)
 	MCFG_CPU_PROGRAM_MAP(hp9k310_map)
 
-	MCFG_DEVICE_ADD(PTM6840_TAG, PTM6840, 0)
-	MCFG_PTM6840_INTERNAL_CLOCK(250000.0f)  // from oscillator module next to the 6840
+	MCFG_DEVICE_ADD(PTM6840_TAG, PTM6840, 250000) // from oscillator module next to the 6840
 	MCFG_PTM6840_EXTERNAL_CLOCKS(250000.0f, 250000.0f, 250000.0f)
 
 	MCFG_SCREEN_ADD( "screen", RASTER)
@@ -307,8 +306,7 @@ static MACHINE_CONFIG_START( hp9k320, hp9k3xx_state )
 	MCFG_CPU_ADD(MAINCPU_TAG, M68020FPU, 16670000)
 	MCFG_CPU_PROGRAM_MAP(hp9k320_map)
 
-	MCFG_DEVICE_ADD(PTM6840_TAG, PTM6840, 0)
-	MCFG_PTM6840_INTERNAL_CLOCK(250000.0f)  // from oscillator module next to the 6840
+	MCFG_DEVICE_ADD(PTM6840_TAG, PTM6840, 250000) // from oscillator module next to the 6840
 	MCFG_PTM6840_EXTERNAL_CLOCKS(250000.0f, 250000.0f, 250000.0f)
 
 	MCFG_SCREEN_ADD( "screen", RASTER)
@@ -323,8 +321,7 @@ static MACHINE_CONFIG_START( hp9k330, hp9k3xx_state )
 	MCFG_CPU_ADD(MAINCPU_TAG, M68020PMMU, 16670000)
 	MCFG_CPU_PROGRAM_MAP(hp9k330_map)
 
-	MCFG_DEVICE_ADD(PTM6840_TAG, PTM6840, 0)
-	MCFG_PTM6840_INTERNAL_CLOCK(250000.0f)  // from oscillator module next to the 6840
+	MCFG_DEVICE_ADD(PTM6840_TAG, PTM6840, 250000) // from oscillator module next to the 6840
 	MCFG_PTM6840_EXTERNAL_CLOCKS(250000.0f, 250000.0f, 250000.0f)
 
 	MCFG_SCREEN_ADD( "screen", RASTER)
@@ -339,8 +336,7 @@ static MACHINE_CONFIG_START( hp9k340, hp9k3xx_state )
 	MCFG_CPU_ADD(MAINCPU_TAG, M68030, 16670000)
 	MCFG_CPU_PROGRAM_MAP(hp9k330_map)
 
-	MCFG_DEVICE_ADD(PTM6840_TAG, PTM6840, 0)
-	MCFG_PTM6840_INTERNAL_CLOCK(250000.0f)  // from oscillator module next to the 6840
+	MCFG_DEVICE_ADD(PTM6840_TAG, PTM6840, 250000) // from oscillator module next to the 6840
 	MCFG_PTM6840_EXTERNAL_CLOCKS(250000.0f, 250000.0f, 250000.0f)
 
 	MCFG_SCREEN_ADD( "screen", RASTER)
@@ -355,8 +351,7 @@ static MACHINE_CONFIG_START( hp9k370, hp9k3xx_state )
 	MCFG_CPU_ADD(MAINCPU_TAG, M68030, 33000000)
 	MCFG_CPU_PROGRAM_MAP(hp9k370_map)
 
-	MCFG_DEVICE_ADD(PTM6840_TAG, PTM6840, 0)
-	MCFG_PTM6840_INTERNAL_CLOCK(250000.0f)  // from oscillator module next to the 6840
+	MCFG_DEVICE_ADD(PTM6840_TAG, PTM6840, 250000) // from oscillator module next to the 6840
 	MCFG_PTM6840_EXTERNAL_CLOCKS(250000.0f, 250000.0f, 250000.0f)
 
 	MCFG_SCREEN_ADD( "screen", RASTER)
@@ -371,8 +366,7 @@ static MACHINE_CONFIG_START( hp9k380, hp9k3xx_state )
 	MCFG_CPU_ADD(MAINCPU_TAG, M68040, 25000000) // 25 MHz?  33?
 	MCFG_CPU_PROGRAM_MAP(hp9k330_map)
 
-	MCFG_DEVICE_ADD(PTM6840_TAG, PTM6840, 0)
-	MCFG_PTM6840_INTERNAL_CLOCK(250000.0f)  // from oscillator module next to the 6840
+	MCFG_DEVICE_ADD(PTM6840_TAG, PTM6840, 250000) // from oscillator module next to the 6840
 	MCFG_PTM6840_EXTERNAL_CLOCKS(250000.0f, 250000.0f, 250000.0f)
 
 	MCFG_SCREEN_ADD( "screen", RASTER)
@@ -387,8 +381,7 @@ static MACHINE_CONFIG_START( hp9k382, hp9k3xx_state )
 	MCFG_CPU_ADD(MAINCPU_TAG, M68040, 25000000) // 25 MHz?  33?
 	MCFG_CPU_PROGRAM_MAP(hp9k382_map)
 
-	MCFG_DEVICE_ADD(PTM6840_TAG, PTM6840, 0)
-	MCFG_PTM6840_INTERNAL_CLOCK(250000.0f)  // from oscillator module next to the 6840
+	MCFG_DEVICE_ADD(PTM6840_TAG, PTM6840, 250000) // from oscillator module next to the 6840
 	MCFG_PTM6840_EXTERNAL_CLOCKS(250000.0f, 250000.0f, 250000.0f)
 
 	MCFG_SCREEN_ADD( "screen", RASTER)
diff --git a/src/mame/drivers/ibmpc.cpp b/src/mame/drivers/ibmpc.cpp
index a5b26b8..0e3db41 100644
--- a/src/mame/drivers/ibmpc.cpp
+++ b/src/mame/drivers/ibmpc.cpp
@@ -352,7 +352,6 @@ static MACHINE_CONFIG_START( ibm5160, ibmpc_state )
 
 	/* software lists */
 	MCFG_SOFTWARE_LIST_ADD("pc_disk_list","ibm5150")
-	MCFG_SOFTWARE_LIST_ADD("xt_disk_list","ibm5160_flop")
 MACHINE_CONFIG_END
 
 
diff --git a/src/mame/drivers/imolagp.cpp b/src/mame/drivers/imolagp.cpp
index 5d490f0..d1ec016 100644
--- a/src/mame/drivers/imolagp.cpp
+++ b/src/mame/drivers/imolagp.cpp
@@ -501,8 +501,8 @@ static MACHINE_CONFIG_START( imolagp, imolagp_state )
 	MCFG_DEVICE_ADD("ppi8255", I8255A, 0)
 	// mode $91 - ports A & C-lower as input, ports B & C-upper as output
 	MCFG_I8255_IN_PORTA_CB(IOPORT("IN0"))
-	MCFG_I8255_IN_PORTB_CB(LOGGER("PPI8255 - unmapped read port B", 0))
-	MCFG_I8255_OUT_PORTB_CB(LOGGER("PPI8255 - unmapped write port B", 0))
+	MCFG_I8255_IN_PORTB_CB(LOGGER("PPI8255 - unmapped read port B"))
+	MCFG_I8255_OUT_PORTB_CB(LOGGER("PPI8255 - unmapped write port B"))
 	MCFG_I8255_IN_PORTC_CB(IOPORT("IN1"))
 
 	/* video hardware */
diff --git a/src/mame/drivers/inder.cpp b/src/mame/drivers/inder.cpp
index b9a9fb2..67c7bf0 100644
--- a/src/mame/drivers/inder.cpp
+++ b/src/mame/drivers/inder.cpp
@@ -35,6 +35,7 @@
 #include "sound/ay8910.h"
 #include "sound/msm5205.h"
 #include "machine/7474.h"
+#include "machine/74157.h"
 #include "inder.lh"
 
 class inder_state : public genpin_class
@@ -49,6 +50,7 @@ public:
 		, m_7a(*this, "7a")
 		, m_9a(*this, "9a")
 		, m_9b(*this, "9b")
+		, m_13(*this, "13")
 		, m_switches(*this, "SW.%u", 0)
 	{ }
 
@@ -77,6 +79,7 @@ public:
 	DECLARE_DRIVER_INIT(inder);
 	DECLARE_DRIVER_INIT(inder1);
 private:
+	void update_mus();
 	bool m_pc0;
 	uint8_t m_game;
 	uint8_t m_portc;
@@ -94,6 +97,7 @@ private:
 	optional_device<ttl7474_device> m_7a;
 	optional_device<ttl7474_device> m_9a;
 	optional_device<ttl7474_device> m_9b;
+	optional_device<hct157_device> m_13;
 	required_ioport_array<11> m_switches;
 };
 
@@ -1232,24 +1236,25 @@ WRITE8_MEMBER( inder_state::sndbank_w )
 	for (i = 0; i < 4; i++)
 		if (!(BIT(data, i)))
 			m_sound_addr = (m_sound_addr & 0x0ffff) | (i << 16);
+	update_mus();
+}
+
+void inder_state::update_mus()
+{
+	if ((m_sound_addr < 0x40000) && (m_sndbank != 0xff))
+		m_13->ba_w(m_p_speech[m_sound_addr]);
+	else
+		m_13->ba_w(0);
 }
 
 WRITE_LINE_MEMBER( inder_state::vck_w )
 {
-	m_9a->clock_w(0);
+	// The order of these writes is sensitive, though the schematic (not to scale)
+	// makes it seem that both 74HCT74 clock inputs should be raised simultaneously
 	m_9b->clock_w(0);
-	m_9a->clock_w(1);
+	m_9a->clock_w(0);
 	m_9b->clock_w(1);
-
-	if ((m_sound_addr < 0x40000) && (m_sndbank != 0xff))
-	{
-		if (!m_pc0)
-			m_msm->data_w(m_p_speech[m_sound_addr] & 15);
-		else
-			m_msm->data_w(m_p_speech[m_sound_addr] >> 4);
-	}
-	else
-		m_msm->data_w(0);
+	m_9a->clock_w(1);
 }
 
 WRITE_LINE_MEMBER( inder_state::qc7a_w )
@@ -1268,6 +1273,7 @@ WRITE_LINE_MEMBER( inder_state::qc9b_w )
 {
 	m_9a->d_w(state);
 	m_9b->d_w(state);
+	m_13->select_w(state);
 }
 
 READ8_MEMBER( inder_state::ppic_r )
@@ -1278,11 +1284,13 @@ READ8_MEMBER( inder_state::ppic_r )
 WRITE8_MEMBER( inder_state::ppia_w )
 {
 	m_sound_addr = (m_sound_addr & 0x3ff00) | data;
+	update_mus();
 }
 
 WRITE8_MEMBER( inder_state::ppib_w )
 {
 	m_sound_addr = (m_sound_addr & 0x300ff) | (data << 8);
+	update_mus();
 }
 
 WRITE8_MEMBER( inder_state::ppic_w )
@@ -1302,14 +1310,17 @@ void inder_state::machine_reset()
 	m_sound_addr = 0;
 	m_sndbank = 0xff;
 	m_row = 0;
-	if (m_7a)
+	if (m_7a.found())
+	{
 		m_7a->clear_w(1);
+		update_mus();
+	}
 }
 
 DRIVER_INIT_MEMBER( inder_state, inder )
 {
 	m_p_speech = memregion("speech")->base();
-	if (m_7a)
+	if (m_7a.found())
 	{
 		m_7a->d_w(0);
 		m_7a->clear_w(0);
@@ -1321,7 +1332,7 @@ DRIVER_INIT_MEMBER( inder_state, inder )
 DRIVER_INIT_MEMBER( inder_state, inder1 )
 {
 	m_p_speech = memregion("speech")->base();
-	if (m_7a)
+	if (m_7a.found())
 	{
 		m_7a->d_w(0);
 		m_7a->clear_w(0);
@@ -1461,6 +1472,9 @@ static MACHINE_CONFIG_START( inder, inder_state )
 
 	MCFG_DEVICE_ADD("9b", TTL7474, 0)
 	MCFG_7474_COMP_OUTPUT_CB(WRITELINE(inder_state, qc9b_w))
+
+	MCFG_DEVICE_ADD("13", HCT157, 0)
+	MCFG_74157_OUT_CB(DEVWRITE8("msm", msm5205_device, data_w))
 MACHINE_CONFIG_END
 
 
diff --git a/src/mame/drivers/isbc.cpp b/src/mame/drivers/isbc.cpp
index f5c5262..2397299 100644
--- a/src/mame/drivers/isbc.cpp
+++ b/src/mame/drivers/isbc.cpp
@@ -12,7 +12,7 @@ isbc86 commands: BYTE WORD REAL EREAL ROMTEST. ROMTEST works, the others hang.
 
 Press capital-U to drop into the monitor on the isbc 86/05 and 86/30
 The 86/05 can boot floppies with the b command but appears to mostly be
-able to deal with 8" disks as it fails to properly load the irmx86 5.25" images.
+able to deal with 256byte sectors so fails to load the irmx 512byte sector images.
 
 ****************************************************************************/
 
@@ -78,7 +78,7 @@ void isbc_state::machine_reset()
 static ADDRESS_MAP_START(rpc86_mem, AS_PROGRAM, 16, isbc_state)
 	ADDRESS_MAP_UNMAP_HIGH
 	AM_RANGE(0x00000, 0xcffff) AM_RAM
-	AM_RANGE(0xfc000, 0xfffff) AM_ROM AM_REGION("user1",0)
+	AM_RANGE(0xf8000, 0xfffff) AM_ROM AM_REGION("user1",0)
 ADDRESS_MAP_END
 
 static ADDRESS_MAP_START(rpc86_io, AS_IO, 16, isbc_state)
@@ -102,6 +102,11 @@ static ADDRESS_MAP_START(isbc8605_io, AS_IO, 16, isbc_state)
 	AM_IMPORT_FROM(rpc86_io)
 ADDRESS_MAP_END
 
+static ADDRESS_MAP_START(isbc8630_io, AS_IO, 16, isbc_state)
+	AM_RANGE(0x0100, 0x0101) AM_DEVWRITE8("isbc_215g", isbc_215g_device, write, 0x00ff)
+	AM_IMPORT_FROM(rpc86_io)
+ADDRESS_MAP_END
+
 static ADDRESS_MAP_START(isbc86_mem, AS_PROGRAM, 16, isbc_state)
 	ADDRESS_MAP_UNMAP_HIGH
 	AM_RANGE(0x00000, 0xfbfff) AM_RAM
@@ -271,12 +276,14 @@ static MACHINE_CONFIG_START( rpc86, isbc_state )
 	MCFG_I8251_DTR_HANDLER(DEVWRITELINE("rs232", rs232_port_device, write_dtr))
 	MCFG_I8251_RTS_HANDLER(DEVWRITELINE("rs232", rs232_port_device, write_rts))
 	MCFG_I8251_RXRDY_HANDLER(DEVWRITELINE("pic_0", pic8259_device, ir6_w))
+	MCFG_I8251_TXRDY_HANDLER(DEVWRITELINE("pic_0", pic8259_device, ir7_w))
 
 	/* video hardware */
 	MCFG_RS232_PORT_ADD("rs232", default_rs232_devices, "terminal")
 	MCFG_RS232_RXD_HANDLER(DEVWRITELINE("uart8251", i8251_device, write_rxd))
 	//MCFG_RS232_CTS_HANDLER(DEVWRITELINE("uart8251", i8251_device, write_cts))
 	MCFG_RS232_DSR_HANDLER(DEVWRITELINE("uart8251", i8251_device, write_dsr))
+	MCFG_DEVICE_CARD_DEVICE_INPUT_DEFAULTS("terminal", isbc286_terminal)
 
 	MCFG_ISBX_SLOT_ADD("sbx1", 0, isbx_cards, nullptr)
 	//MCFG_ISBX_SLOT_MINTR0_CALLBACK(DEVWRITELINE("pic_0", pic8259_device, ir3_w))
@@ -295,6 +302,14 @@ static MACHINE_CONFIG_DERIVED( isbc8605, rpc86 )
 	MCFG_ISBC_208_IRQ(DEVWRITELINE("pic_0", pic8259_device, ir5_w))
 MACHINE_CONFIG_END
 
+static MACHINE_CONFIG_DERIVED( isbc8630, rpc86 )
+	MCFG_CPU_MODIFY("maincpu")
+	MCFG_CPU_IO_MAP(isbc8630_io)
+
+	MCFG_ISBC_215_ADD("isbc_215g", 0x100, "maincpu")
+	MCFG_ISBC_215_IRQ(DEVWRITELINE("pic_0", pic8259_device, ir5_w))
+MACHINE_CONFIG_END
+
 static MACHINE_CONFIG_START( isbc286, isbc_state )
 	/* basic machine hardware */
 	MCFG_CPU_ADD("maincpu", I80286, XTAL_16MHz/2)
@@ -373,16 +388,22 @@ ROM_START( isbc86 )
 ROM_END
 
 ROM_START( isbc8605 )
-	ROM_REGION( 0x4000, "user1", ROMREGION_ERASEFF )
-	ROM_LOAD( "i8605mon.bin", 0x0000, 0x4000, CRC(e16acb6e) SHA1(eb9a3fd21f7609d44f8052b6a0603ecbb52dc3f3))
+	ROM_REGION( 0x8000, "user1", ROMREGION_ERASEFF )
+	ROM_LOAD( "i8605mon.bin", 0x4000, 0x4000, CRC(e16acb6e) SHA1(eb9a3fd21f7609d44f8052b6a0603ecbb52dc3f3))
 ROM_END
 
 ROM_START( isbc8630 )
-	ROM_REGION( 0x4000, "user1", ROMREGION_ERASEFF )
-	ROM_LOAD16_BYTE( "143780-001_isdm_for_isbc_86-30_socket_u57_i2732a.bin", 0x0000, 0x1000, CRC(db0ef880) SHA1(8ef296066d16881217618e54b410d12157f318ea))
-	ROM_LOAD16_BYTE( "143782-001_isdm_for_isbc_86-30_socket_u39_i2732a.bin", 0x0001, 0x1000, CRC(ea1ebe78) SHA1(f03b63659e8f5e96f481dbc6c2ddef1d22850ebb))
-	ROM_LOAD16_BYTE( "143781-001_isdm_for_isbc_86-30_socket_u58_i2732a.bin", 0x2000, 0x1000, CRC(93732612) SHA1(06e751d0f5ab1fe2c52fd79f6f4725ccf3379791))
-	ROM_LOAD16_BYTE( "143783-001_isdm_for_isbc_86-30_socket_u40_i2732a.bin", 0x2001, 0x1000, CRC(337102d5) SHA1(535f63d24c3948187b208ea594f979bc33579a15))
+	ROM_REGION( 0x8000, "user1", ROMREGION_ERASEFF )
+	ROM_SYSTEM_BIOS( 0, "14378", "14378" )
+	ROMX_LOAD( "143780-001_isdm_for_isbc_86-30_socket_u57_i2732a.bin", 0x4000, 0x1000, CRC(db0ef880) SHA1(8ef296066d16881217618e54b410d12157f318ea), ROM_SKIP(1) | ROM_BIOS(1))
+	ROMX_LOAD( "143782-001_isdm_for_isbc_86-30_socket_u39_i2732a.bin", 0x4001, 0x1000, CRC(ea1ebe78) SHA1(f03b63659e8f5e96f481dbc6c2ddef1d22850ebb), ROM_SKIP(1) | ROM_BIOS(1))
+	ROMX_LOAD( "143781-001_isdm_for_isbc_86-30_socket_u58_i2732a.bin", 0x6000, 0x1000, CRC(93732612) SHA1(06e751d0f5ab1fe2c52fd79f6f4725ccf3379791), ROM_SKIP(1) | ROM_BIOS(1))
+	ROMX_LOAD( "143783-001_isdm_for_isbc_86-30_socket_u40_i2732a.bin", 0x6001, 0x1000, CRC(337102d5) SHA1(535f63d24c3948187b208ea594f979bc33579a15), ROM_SKIP(1) | ROM_BIOS(1))
+	ROM_SYSTEM_BIOS( 1, "14503", "14503" )
+	ROMX_LOAD( "145032-001_u57.bin", 0x0000, 0x2000, CRC(09a24dea) SHA1(e21277f1d4d72e0858846f7293ac48417b392e3b), ROM_SKIP(1) | ROM_BIOS(2))
+	ROMX_LOAD( "145030-001_u39.bin", 0x0001, 0x2000, CRC(c58f3a98) SHA1(76f6d5be8ea6854a98f6555320cfcdb814e5c633), ROM_SKIP(1) | ROM_BIOS(2))
+	ROMX_LOAD( "145033-001_u58.bin", 0x4000, 0x2000, CRC(496aca5f) SHA1(c09f4d2254ece1eb139ef5fd4ad0ce6a55376da5), ROM_SKIP(1) | ROM_BIOS(2))
+	ROMX_LOAD( "145031-001_u40.bin", 0x4001, 0x2000, CRC(150fcd90) SHA1(4bca0f46b9b05ef0124bac5dea09ddd952e73af2), ROM_SKIP(1) | ROM_BIOS(2))
 ROM_END
 
 ROM_START( isbc286 )
@@ -405,19 +426,26 @@ ROM_START( isbc2861 )
 	ROMX_LOAD( "rmx286-_in_socket_u75_on_isbc_286-10.bin.u75", 0x8001, 0x4000, CRC(68c3eb50) SHA1(3eeef2676e4fb187adb8ab50645f4bd172426c15), ROM_SKIP(1) | ROM_BIOS(2))
 ROM_END
 
+ROM_START( isbc28612 )
+	ROM_REGION( 0x10000, "user1", ROMREGION_ERASEFF )
+	ROM_LOAD16_BYTE( "176346-001.bin", 0x0000, 0x8000, CRC(f86c8be5) SHA1(e2bb16b0aeb718219e65d61edabd7838ef34c560))
+	ROM_LOAD16_BYTE( "176346-002.bin", 0x0001, 0x8000, CRC(b964c6c3) SHA1(c3de8541182e32b3568fde77da8c435eab397498))
+ROM_END
+
 ROM_START( rpc86 )
-	ROM_REGION( 0x4000, "user1", ROMREGION_ERASEFF )
-	ROM_LOAD16_BYTE( "145068-001.bin", 0x0001, 0x1000, CRC(0fa9db83) SHA1(4a44f8683c263c9ef6850cbe05aaa73f4d4d4e06))
-	ROM_LOAD16_BYTE( "145069-001.bin", 0x2001, 0x1000, CRC(1692a076) SHA1(0ce3a4a867cb92340871bb8f9c3e91ce2984c77c))
-	ROM_LOAD16_BYTE( "145070-001.bin", 0x0000, 0x1000, CRC(8c8303ef) SHA1(60f94daa76ab9dea6e309ac580152eb212b847a0))
-	ROM_LOAD16_BYTE( "145071-001.bin", 0x2000, 0x1000, CRC(a49681d8) SHA1(e81f8b092cfa2d1737854b1fa270a4ce07d61a9f))
+	ROM_REGION( 0x8000, "user1", ROMREGION_ERASEFF )
+	ROM_LOAD16_BYTE( "145068-001.bin", 0x4001, 0x1000, CRC(0fa9db83) SHA1(4a44f8683c263c9ef6850cbe05aaa73f4d4d4e06))
+	ROM_LOAD16_BYTE( "145069-001.bin", 0x6001, 0x1000, CRC(1692a076) SHA1(0ce3a4a867cb92340871bb8f9c3e91ce2984c77c))
+	ROM_LOAD16_BYTE( "145070-001.bin", 0x4000, 0x1000, CRC(8c8303ef) SHA1(60f94daa76ab9dea6e309ac580152eb212b847a0))
+	ROM_LOAD16_BYTE( "145071-001.bin", 0x6000, 0x1000, CRC(a49681d8) SHA1(e81f8b092cfa2d1737854b1fa270a4ce07d61a9f))
 ROM_END
 /* Driver */
 
 /*    YEAR  NAME    PARENT  COMPAT   MACHINE    INPUT    INIT COMPANY   FULLNAME       FLAGS */
-COMP( 19??, rpc86,    0,       0,    rpc86,      isbc, driver_device,    0,   "Intel",   "RPC 86",MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
-COMP( 1978, isbc86,   0,       0,    isbc86,     isbc, driver_device,    0,   "Intel",   "iSBC 86/12A",MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
-COMP( 1981, isbc8605, 0,       0,    isbc8605,   isbc, driver_device,    0,   "Intel",   "iSBC 86/05",MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
-COMP( 1981, isbc8630, 0,       0,    rpc86,      isbc, driver_device,    0,   "Intel",   "iSBC 86/30",MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
-COMP( 19??, isbc286,  0,       0,    isbc286,    isbc, driver_device,    0,   "Intel",   "iSBC 286",MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
-COMP( 1983, isbc2861, 0,       0,    isbc2861,   isbc, driver_device,    0,   "Intel",   "iSBC 286/10", MACHINE_NO_SOUND)
+COMP( 19??, rpc86,    0,       0,    rpc86,      isbc, driver_device,    0,   "Intel",   "RPC 86",MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW)
+COMP( 1978, isbc86,   0,       0,    isbc86,     isbc, driver_device,    0,   "Intel",   "iSBC 86/12A",MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW)
+COMP( 1981, isbc8605, 0,       0,    isbc8605,   isbc, driver_device,    0,   "Intel",   "iSBC 86/05",MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW)
+COMP( 1981, isbc8630, 0,       0,    isbc8630,   isbc, driver_device,    0,   "Intel",   "iSBC 86/30",MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW)
+COMP( 19??, isbc286,  0,       0,    isbc286,    isbc, driver_device,    0,   "Intel",   "iSBC 286",MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW)
+COMP( 1983, isbc2861, 0,       0,    isbc2861,   isbc, driver_device,    0,   "Intel",   "iSBC 286/10", MACHINE_NO_SOUND_HW)
+COMP( 1983, isbc28612,0,       0,    isbc2861,   isbc, driver_device,    0,   "Intel",   "iSBC 286/12", MACHINE_NO_SOUND_HW)
diff --git a/src/mame/drivers/iteagle.cpp b/src/mame/drivers/iteagle.cpp
index 79c605c..6d67650 100644
--- a/src/mame/drivers/iteagle.cpp
+++ b/src/mame/drivers/iteagle.cpp
@@ -183,7 +183,7 @@ MACHINE_CONFIG_END
 
 static MACHINE_CONFIG_DERIVED( gtfore01, iteagle )
 	MCFG_DEVICE_MODIFY(PCI_ID_FPGA)
-	MCFG_ITEAGLE_FPGA_INIT(0x00000401, 0x0b0b0b)
+	MCFG_ITEAGLE_FPGA_INIT(0x01000401, 0x0b0b0b)
 	MCFG_DEVICE_MODIFY(PCI_ID_EEPROM)
 	MCFG_ITEAGLE_EEPROM_INIT(0x0401, 0x7)
 MACHINE_CONFIG_END
@@ -290,8 +290,8 @@ static INPUT_PORTS_START( iteagle )
 	PORT_BIT( 0xfe00, IP_ACTIVE_LOW, IPT_UNKNOWN )
 
 	PORT_START("SYSTEM")
-	PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_TILT ) PORT_NAME( "Test" )
-	PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_SERVICE )
+	PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_NAME( "Service" )
+	PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_SERVICE1 )
 	PORT_BIT( 0x000c, IP_ACTIVE_LOW, IPT_UNKNOWN )
 	PORT_DIPNAME( 0x0010, 0x00, "SW51-1" )
 	PORT_DIPSETTING(0x00, "Normal" )
diff --git a/src/mame/drivers/itech32.cpp b/src/mame/drivers/itech32.cpp
index 06317dc..ad5e10a 100644
--- a/src/mame/drivers/itech32.cpp
+++ b/src/mame/drivers/itech32.cpp
@@ -2139,8 +2139,8 @@ ROM_END
 
 ROM_START( pairs )  /* Version 1.2 (3-tier board set: P/N 1059 Rev 3, P/N 1061 Rev 1 &  P/N 1060 Rev 0) */
 	ROM_REGION16_BE( 0x80000, "user1", 0 )
-	ROM_LOAD16_BYTE( "pair0_u83_v1.2.u83", 0x00000, 0x20000, CRC(a9c761d8) SHA1(2618c9c3f336cf30f760fd88f12c09985cfd4ee7) )
-	ROM_LOAD16_BYTE( "pair1_u88_v1.2.u88", 0x00001, 0x20000, CRC(5141eb86) SHA1(3bb10d588e6334a33e5c2c468651699e84f46cdc) )
+	ROM_LOAD16_BYTE( "pair0_u83_x_v1.2.u83", 0x00000, 0x20000, CRC(a9c761d8) SHA1(2618c9c3f336cf30f760fd88f12c09985cfd4ee7) )
+	ROM_LOAD16_BYTE( "pair1_u88_x_v1.2.u88", 0x00001, 0x20000, CRC(5141eb86) SHA1(3bb10d588e6334a33e5c2c468651699e84f46cdc) )
 
 	ROM_REGION( 0x28000, "soundcpu", 0 )
 	ROM_LOAD( "pairsnd_u17_v1.u17", 0x10000, 0x18000, CRC(7a514cfd) SHA1(ef5bc74c9560d2c058298051070fa748e58f07e1) )
diff --git a/src/mame/drivers/jpmsys5.cpp b/src/mame/drivers/jpmsys5.cpp
index 458808a..80fc2dc 100644
--- a/src/mame/drivers/jpmsys5.cpp
+++ b/src/mame/drivers/jpmsys5.cpp
@@ -669,8 +669,7 @@ static MACHINE_CONFIG_START( jpmsys5v, jpmsys5_state )
 	MCFG_PIA_IRQB_HANDLER(WRITELINE(jpmsys5_state, pia_irq))
 
 	/* 6840 PTM */
-	MCFG_DEVICE_ADD("6840ptm", PTM6840, 0)
-	MCFG_PTM6840_INTERNAL_CLOCK(1000000)
+	MCFG_DEVICE_ADD("6840ptm", PTM6840, 1000000)
 	MCFG_PTM6840_EXTERNAL_CLOCKS(0, 0, 0)
 	MCFG_PTM6840_OUT0_CB(WRITELINE(jpmsys5_state, u26_o1_callback))
 	MCFG_PTM6840_IRQ_CB(WRITELINE(jpmsys5_state, ptm_irq))
@@ -874,8 +873,7 @@ MACHINE_CONFIG_START( jpmsys5_ym, jpmsys5_state )
 	MCFG_PIA_IRQB_HANDLER(WRITELINE(jpmsys5_state, pia_irq))
 
 	/* 6840 PTM */
-	MCFG_DEVICE_ADD("6840ptm", PTM6840, 0)
-	MCFG_PTM6840_INTERNAL_CLOCK(1000000)
+	MCFG_DEVICE_ADD("6840ptm", PTM6840, 1000000)
 	MCFG_PTM6840_EXTERNAL_CLOCKS(0, 0, 0)
 	MCFG_PTM6840_OUT0_CB(WRITELINE(jpmsys5_state, u26_o1_callback))
 	MCFG_PTM6840_IRQ_CB(WRITELINE(jpmsys5_state, ptm_irq))
@@ -927,8 +925,7 @@ MACHINE_CONFIG_START( jpmsys5, jpmsys5_state )
 	MCFG_PIA_IRQB_HANDLER(WRITELINE(jpmsys5_state, pia_irq))
 
 	/* 6840 PTM */
-	MCFG_DEVICE_ADD("6840ptm", PTM6840, 0)
-	MCFG_PTM6840_INTERNAL_CLOCK(1000000)
+	MCFG_DEVICE_ADD("6840ptm", PTM6840, 1000000)
 	MCFG_PTM6840_EXTERNAL_CLOCKS(0, 0, 0)
 	MCFG_PTM6840_OUT0_CB(WRITELINE(jpmsys5_state, u26_o1_callback))
 	MCFG_PTM6840_IRQ_CB(WRITELINE(jpmsys5_state, ptm_irq))
diff --git a/src/mame/drivers/k28.cpp b/src/mame/drivers/k28.cpp
index 701ac2d..c68620e 100644
--- a/src/mame/drivers/k28.cpp
+++ b/src/mame/drivers/k28.cpp
@@ -16,7 +16,6 @@
 
   TODO:
   - external module support (no dumps yet)
-  - SC-01 frog speech is why this driver is marked NOT_WORKING
 
 ***************************************************************************/
 
@@ -277,7 +276,7 @@ WRITE8_MEMBER(k28_state::mcu_p0_w)
 
 	// d3: SC-01 strobe, latch phoneme on rising edge
 	int strobe = data >> 3 & 1;
-	if (!strobe && m_speech_strobe)
+	if (strobe && !m_speech_strobe)
 		m_speech->write(space, 0, m_phoneme);
 	m_speech_strobe = strobe;
 
@@ -377,7 +376,7 @@ WRITE8_MEMBER(k28_state::mcu_prog_w)
 READ8_MEMBER(k28_state::mcu_t1_r)
 {
 	// 8021 T1: SC-01 A/R pin
-	return m_speech->request();
+	return m_speech->request() ? 1 : 0;
 }
 
 
@@ -516,4 +515,4 @@ ROM_END
 
 
 /*    YEAR  NAME PARENT COMPAT MACHINE INPUT INIT              COMPANY, FULLNAME, FLAGS */
-COMP( 1981, k28, 0,     0,     k28,    k28,  driver_device, 0, "Tiger Electronics", "K28: Talking Learning Computer (model 7-230)", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING )
+COMP( 1981, k28, 0,     0,     k28,    k28,  driver_device, 0, "Tiger Electronics", "K28: Talking Learning Computer (model 7-230)", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_SOUND )
diff --git a/src/mame/drivers/kaneko16.cpp b/src/mame/drivers/kaneko16.cpp
index 6785cf1..4535596 100644
--- a/src/mame/drivers/kaneko16.cpp
+++ b/src/mame/drivers/kaneko16.cpp
@@ -2518,11 +2518,83 @@ DRIVER_INIT_MEMBER( kaneko16_state, kaneko16 )
 	kaneko16_unscramble_tiles("gfx3");
 }
 
-DRIVER_INIT_MEMBER( kaneko16_berlwall_state, berlwall )
+/*
+
+berlwallt original bug ?
+
+info from SebV:
+
+After about level 5 or so, if you insert a coin when the continue screen
+pops up, an error message "Copy Board" pops up.
+----------------------------------------
+Happened to me when player dies, at level 4.
+The message is not written in ROM, its sprite ram address is (always?)
+$30fd40
+Routine $337d2 writes it (and routine $5c8c erases it)
+The 'COPY BOARD!' message in stored in ROM directly as sprite number
+($1cfa8)
+
+$20288a : seems to contain the level number (initialized to 2 (?) when a
+game is started, and is incremented by 1 once a level is finished)
+
+01CF3E: move.b  $20288a.l, D0
+01CF44: cmpi.b  #$d, D0
+01CF48: bcs     1cf76                   ; branch not taken -=> 'COPY BOARD!'
+01CF4A: movem.l D0/A0-A2, -(A7)
+01CF4E: movea.l A0, A1
+01CF50: lea     ($4c,PC), A0; ($1cf9e)
+01CF54: nop
+01CF56: lea     ($a,A0), A0             ; A0 = $1cfa8 = 'COPY BOARD!'
+01CF5A: lea     $30e064.l, A1
+01CF60: lea     (-$64,A1), A1
+01CF64: lea     ($1d40,A1), A1
+01CF68: move.b  #$80, D1
+01CF6C: jsr     $33776.l                ; display routine
+01CF72: movem.l (A7)+, D0/A0-A2
+01CF76:
+
+berlwall  levels: 1-1,2,3(anim),...
+berlwallt levels: 1-1(anim)2-1/2/3/4/5(anim)3-1/2/3/4/5(anim)4-1(*)
+
+note: berlwall may be genuine while berlwallt may be bootleg! because
+stage 1-1 of berlwallt is stage 1-3 of berlwall, and berlwall has
+explanation ingame.
+(TAFA flyers exist for both berlwall and berlwallt player graphics)
+--------------------------------------------------------------------------------
+*/
+// TODO: this is certainly a protection issue, the level number variable can go up to 0x2f, which is way bigger than 0xd.
+// Sprite DMA decryption? @see berlwall_spriteram_r
+void kaneko16_berlwall_state::patch_protection(uint32_t bra_offset,uint16_t bra_value,uint16_t checksum)
+{
+	uint16_t *ROM = (uint16_t *)memregion("maincpu")->base();
+
+	ROM[bra_offset/2] = bra_value;
+	ROM[0x3fffe/2] = checksum;
+}
+
+DRIVER_INIT_MEMBER(kaneko16_berlwall_state, berlwall_common)
 {
 	kaneko16_unscramble_tiles("gfx2");
 }
 
+DRIVER_INIT_MEMBER( kaneko16_berlwall_state, berlwall )
+{
+	DRIVER_INIT_CALL(berlwall_common);
+	patch_protection(0x1a3ea,0x602c,0xc40d);
+}
+
+DRIVER_INIT_MEMBER( kaneko16_berlwall_state, berlwallt )
+{
+	DRIVER_INIT_CALL(berlwall_common);
+	patch_protection(0x1cf48,0x602c,0xaed4);
+}
+
+DRIVER_INIT_MEMBER( kaneko16_berlwall_state, berlwallk )
+{
+	DRIVER_INIT_CALL(berlwall_common);
+	patch_protection(0x1ceb0,0x602c,0x8364);
+}
+
 DRIVER_INIT_MEMBER( kaneko16_state, samplebank )
 {
 	kaneko16_unscramble_tiles("gfx2");
@@ -2738,51 +2810,6 @@ ROM_START( berlwall )
 	ROM_LOAD( "bw_u54.u54", 0x400, 0x0117, NO_DUMP)
 ROM_END
 
-
-/*
-berlwallt original bug ?
-
-info from SebV:
-
-After about level 5 or so, if you insert a coin when the continue screen
-pops up, an error message "Copy Board" pops up.
-----------------------------------------
-Happened to me when player dies, at level 4.
-The message is not written in ROM, its sprite ram address is (always?)
-$30fd40
-Routine $337d2 writes it (and routine $5c8c erases it)
-The 'COPY BOARD!' message in stored in ROM directly as sprite number
-($1cfa8)
-
-$20288a : seems to contain the level number (initialized to 2 (?) when a
-game is started, and is incremented by 1 once a level is finished)
-
-01CF3E: move.b  $20288a.l, D0
-01CF44: cmpi.b  #$d, D0
-01CF48: bcs     1cf76                   ; branch not taken -=> 'COPY BOARD!'
-01CF4A: movem.l D0/A0-A2, -(A7)
-01CF4E: movea.l A0, A1
-01CF50: lea     ($4c,PC), A0; ($1cf9e)
-01CF54: nop
-01CF56: lea     ($a,A0), A0             ; A0 = $1cfa8 = 'COPY BOARD!'
-01CF5A: lea     $30e064.l, A1
-01CF60: lea     (-$64,A1), A1
-01CF64: lea     ($1d40,A1), A1
-01CF68: move.b  #$80, D1
-01CF6C: jsr     $33776.l                ; display routine
-01CF72: movem.l (A7)+, D0/A0-A2
-01CF76:
-
-berlwall  levels: 1-1,2,3(anim),...
-berlwallt levels: 1-1(anim)2-1/2/3/4/5(anim)3-1/2/3/4/5(anim)4-1(*)
-
-note: berlwall may be genuine while berlwallt may be bootleg! because
-stage 1-1 of berlwallt is stage 1-3 of berlwall, and berlwall has
-explanation ingame.
-(TAFA flyers exist for both berlwall and berlwallt player graphics)
---------------------------------------------------------------------------------
-*/
-
 ROM_START( berlwallt )
 	ROM_REGION( 0x040000, "maincpu", 0 )            /* 68000 Code */
 	ROM_LOAD16_BYTE( "bw100a.u23", 0x000000, 0x020000, CRC(e6bcb4eb) SHA1(220b8fddc79230b4f6a8cf33e1035355c485e8d1) )
@@ -4441,9 +4468,9 @@ DRIVER_INIT_MEMBER( kaneko16_shogwarr_state, brapboys )
 ***************************************************************************/
 
 GAME( 1991, berlwall, 0,        berlwall, berlwall, kaneko16_berlwall_state, berlwall, ROT0,  "Kaneko", "The Berlin Wall", MACHINE_SUPPORTS_SAVE )
-GAME( 1991, berlwallt,berlwall, berlwall, berlwallt,kaneko16_berlwall_state, berlwall, ROT0,  "Kaneko", "The Berlin Wall (bootleg?)", MACHINE_SUPPORTS_SAVE )
-GAME( 1991, berlwallk,berlwall, berlwall, berlwallk,kaneko16_berlwall_state, berlwall, ROT0,  "Kaneko (Inter license)", "The Berlin Wall (Korea)", MACHINE_SUPPORTS_SAVE )
-GAME( 1994, packbang, 0,        berlwall, packbang, kaneko16_berlwall_state, berlwall, ROT90, "Kaneko", "Pack'n Bang Bang (prototype)", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_GRAPHICS ) // priorities between stages?
+GAME( 1991, berlwallt,berlwall, berlwall, berlwallt,kaneko16_berlwall_state, berlwallt, ROT0,  "Kaneko", "The Berlin Wall (bootleg?)", MACHINE_SUPPORTS_SAVE )
+GAME( 1991, berlwallk,berlwall, berlwall, berlwallk,kaneko16_berlwall_state, berlwallk, ROT0,  "Kaneko (Inter license)", "The Berlin Wall (Korea)", MACHINE_SUPPORTS_SAVE )
+GAME( 1994, packbang, 0,        berlwall, packbang, kaneko16_berlwall_state, berlwall_common, ROT90, "Kaneko", "Pack'n Bang Bang (prototype)", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_GRAPHICS ) // priorities between stages?
 
 GAME( 1991, mgcrystl, 0,        mgcrystl, mgcrystl, kaneko16_state,          kaneko16, ROT0,  "Kaneko", "Magical Crystals (World, 92/01/10)", MACHINE_SUPPORTS_SAVE )
 GAME( 1991, mgcrystlo,mgcrystl, mgcrystl, mgcrystl, kaneko16_state,          kaneko16, ROT0,  "Kaneko", "Magical Crystals (World, 91/12/10)", MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/drivers/koftball.cpp b/src/mame/drivers/koftball.cpp
index 8619649..672fdc1 100644
--- a/src/mame/drivers/koftball.cpp
+++ b/src/mame/drivers/koftball.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /*
 King Of Football (c)1995 BMC
diff --git a/src/mame/drivers/koikoi.cpp b/src/mame/drivers/koikoi.cpp
index 980c0b6..e0806a6 100644
--- a/src/mame/drivers/koikoi.cpp
+++ b/src/mame/drivers/koikoi.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina, David Haywood
 /***************************************************************************
 
diff --git a/src/mame/drivers/konamigx.cpp b/src/mame/drivers/konamigx.cpp
index 9f240ac..e58a552 100644
--- a/src/mame/drivers/konamigx.cpp
+++ b/src/mame/drivers/konamigx.cpp
@@ -3707,7 +3707,17 @@ ROM_END
 
 MACHINE_START_MEMBER(konamigx_state,konamigx)
 {
+	save_item(NAME(m_sound_ctrl));
+	save_item(NAME(m_sound_intck));
+
+	save_item(NAME(m_gx_wrport1_0));
 	save_item(NAME(m_gx_wrport1_1));
+	save_item(NAME(m_gx_wrport2));
+
+	save_item(NAME(m_gx_rdport1_3));
+	save_item(NAME(m_gx_syncen));
+	save_item(NAME(m_suspension_active));
+	save_item(NAME(m_prev_pixel_clock));
 }
 
 MACHINE_RESET_MEMBER(konamigx_state,konamigx)
diff --git a/src/mame/drivers/kopunch.cpp b/src/mame/drivers/kopunch.cpp
index cde3048..37ef8db 100644
--- a/src/mame/drivers/kopunch.cpp
+++ b/src/mame/drivers/kopunch.cpp
@@ -244,13 +244,13 @@ static MACHINE_CONFIG_START( kopunch, kopunch_state )
 	MCFG_DEVICE_ADD("ppi8255_1", I8255A, 0)
 	// $34 - always $80 (PPI mode 0, ports A & B & C as output)
 	MCFG_I8255_OUT_PORTA_CB(WRITE8(kopunch_state, coin_w))
-	MCFG_I8255_OUT_PORTB_CB(LOGGER("PPI8255 - unmapped write port B", 0))
-	MCFG_I8255_OUT_PORTC_CB(LOGGER("PPI8255 - unmapped write port C", 0))
+	MCFG_I8255_OUT_PORTB_CB(LOGGER("PPI8255 - unmapped write port B"))
+	MCFG_I8255_OUT_PORTC_CB(LOGGER("PPI8255 - unmapped write port C"))
 
 	MCFG_DEVICE_ADD("ppi8255_2", I8255A, 0)
 	// $38 - always $89 (PPI mode 0, ports A & B as output, port C as input)
 	MCFG_I8255_OUT_PORTA_CB(WRITE8(kopunch_state, lamp_w))
-	MCFG_I8255_OUT_PORTB_CB(LOGGER("PPI8255 - unmapped write port B", 0))
+	MCFG_I8255_OUT_PORTB_CB(LOGGER("PPI8255 - unmapped write port B"))
 	MCFG_I8255_IN_PORTC_CB(IOPORT("DSW"))
 
 	MCFG_DEVICE_ADD("ppi8255_3", I8255A, 0)
diff --git a/src/mame/drivers/ksayakyu.cpp b/src/mame/drivers/ksayakyu.cpp
index dbedec9..fa415d7 100644
--- a/src/mame/drivers/ksayakyu.cpp
+++ b/src/mame/drivers/ksayakyu.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /*
 Kusayakyuu (Sandlot Baseball)
diff --git a/src/mame/drivers/ksys573.cpp b/src/mame/drivers/ksys573.cpp
index cfd6a8f..3db748f 100644
--- a/src/mame/drivers/ksys573.cpp
+++ b/src/mame/drivers/ksys573.cpp
@@ -3967,24 +3967,24 @@ ROM_START( hndlchmp )
 	SYS573_BIOS_A
 
 	ROM_REGION( 0x200000, "29f016a.31m", 0 ) /* onboard flash */
-	ROM_LOAD( "710ja.31m",    0x000000, 0x200000, CRC(f5f71b1d) SHA1(7d518e5333f44e6ec921a1e882df970953814b6e) )
+	ROM_LOAD( "710jab.31m",   0x000000, 0x200000, CRC(f5f71b1d) SHA1(7d518e5333f44e6ec921a1e882df970953814b6e) )
 	ROM_REGION( 0x200000, "29f016a.27m", 0 ) /* onboard flash */
-	ROM_LOAD( "710ja.27m",    0x000000, 0x200000, CRC(b3d8c037) SHA1(678b88c37111d1fde8996c7d71b66ec1c4f161fe) )
+	ROM_LOAD( "710jab.27m",   0x000000, 0x200000, CRC(b3d8c037) SHA1(678b88c37111d1fde8996c7d71b66ec1c4f161fe) )
 	ROM_REGION( 0x200000, "29f016a.31l", 0 ) /* onboard flash */
-	ROM_LOAD( "710ja.31l",    0x000000, 0x200000, CRC(78e8556c) SHA1(9f6bb651ddeb042ebf1ba057d4932494149f47d6) )
+	ROM_LOAD( "710jab.31l",   0x000000, 0x200000, CRC(78e8556c) SHA1(9f6bb651ddeb042ebf1ba057d4932494149f47d6) )
 	ROM_REGION( 0x200000, "29f016a.27l", 0 ) /* onboard flash */
-	ROM_LOAD( "710ja.27l",    0x000000, 0x200000, CRC(f6a87155) SHA1(269bfdf05ee4ab2e4b87b6e92045e56d0557a576) )
+	ROM_LOAD( "710jab.27l",   0x000000, 0x200000, CRC(f6a87155) SHA1(269bfdf05ee4ab2e4b87b6e92045e56d0557a576) )
 	ROM_REGION( 0x200000, "29f016a.31j", 0 ) /* onboard flash */
-	ROM_LOAD( "710ja.31j",    0x000000, 0x200000, CRC(bdc05d16) SHA1(ee397950f7e7e910fdc05737f99604e43d288719) )
+	ROM_LOAD( "710jab.31j",   0x000000, 0x200000, CRC(bdc05d16) SHA1(ee397950f7e7e910fdc05737f99604e43d288719) )
 	ROM_REGION( 0x200000, "29f016a.27j", 0 ) /* onboard flash */
-	ROM_LOAD( "710ja.27j",    0x000000, 0x200000, CRC(ad925ed3) SHA1(e3222308961851cccee2de9da804f74854907451) )
+	ROM_LOAD( "710jab.27j",   0x000000, 0x200000, CRC(ad925ed3) SHA1(e3222308961851cccee2de9da804f74854907451) )
 	ROM_REGION( 0x200000, "29f016a.31h", 0 ) /* onboard flash */
-	ROM_LOAD( "710ja.31h",    0x000000, 0x200000, CRC(a0293108) SHA1(2e5651a4c1b8e021cc3060db138c9fe7c28caa3b) )
+	ROM_LOAD( "710jab.31h",   0x000000, 0x200000, CRC(a0293108) SHA1(2e5651a4c1b8e021cc3060db138c9fe7c28caa3b) )
 	ROM_REGION( 0x200000, "29f016a.27h", 0 ) /* onboard flash */
-	ROM_LOAD( "710ja.27h",    0x000000, 0x200000, CRC(aed26efe) SHA1(20b6fccd0bc5495d8258b976f72d330d6315c6f6) )
+	ROM_LOAD( "710jab.27h",   0x000000, 0x200000, CRC(aed26efe) SHA1(20b6fccd0bc5495d8258b976f72d330d6315c6f6) )
 
 	ROM_REGION( 0x002000, "m48t58", 0 )
-	ROM_LOAD( "710ja.22h",    0x000000, 0x002000, CRC(b784de91) SHA1(048157e9ad6df46656dbac6349b0c821254e1c37) )
+	ROM_LOAD( "710jab.22h",   0x000000, 0x002000, CRC(b784de91) SHA1(048157e9ad6df46656dbac6349b0c821254e1c37) )
 ROM_END
 
 ROM_START( gchgchmp )
@@ -4714,9 +4714,34 @@ ROM_START( stepchmp )
 	ROM_LOAD( "gq930ja.27h",  0x000000, 0x200000, CRC(256f0794) SHA1(f95d5a8a53dea4d1f4d766124e94ee103cc1e3b2) )
 ROM_END
 
+ROM_START( strgchmp )
+	SYS573_BIOS_A
+
+	ROM_REGION( 0x200000, "29f016a.31m", 0 ) /* onboard flash */
+	ROM_LOAD( "710uaa.31m",   0x000000, 0x200000, CRC(389f8acb) SHA1(db80af29d53f737a6affd1afd18cce050c294fa6) )
+	ROM_REGION( 0x200000, "29f016a.27m", 0 ) /* onboard flash */
+	ROM_LOAD( "710uaa.27m",   0x000000, 0x200000, CRC(5b5c6e4d) SHA1(a5ad9a459504dfb7ada0148f590f777a604549e9) )
+	ROM_REGION( 0x200000, "29f016a.31l", 0 ) /* onboard flash */
+	ROM_LOAD( "710uaa.31l",   0x000000, 0x200000, CRC(fd9fd9b1) SHA1(f1536f62f68d80cabd5d58e8dfa14a8b3e9a6ae3) )
+	ROM_REGION( 0x200000, "29f016a.27l", 0 ) /* onboard flash */
+	ROM_LOAD( "710uaa.27l",   0x000000, 0x200000, CRC(a0e9b72b) SHA1(7272c54c5dc1d1df2427e301e5a10083c9db1967) )
+	ROM_REGION( 0x200000, "29f016a.31j", 0 ) /* onboard flash */
+	ROM_LOAD( "710uaa.31j",   0x000000, 0x200000, CRC(bf6ebc47) SHA1(59a4812e79c9695a0d161fd62534bbb4ae84a4bc) )
+	ROM_REGION( 0x200000, "29f016a.27j", 0 ) /* onboard flash */
+	ROM_LOAD( "710uaa.27j",   0x000000, 0x200000, CRC(79669ebd) SHA1(45828fd6c0b63666963c8f3b7cc5d508bc06b845) )
+	ROM_REGION( 0x200000, "29f016a.31h", 0 ) /* onboard flash */
+	ROM_LOAD( "710uaa.31h",   0x000000, 0x200000, CRC(2a41c844) SHA1(ffa36fef3abc90f2e25e79ccbda199d614edf034) )
+	ROM_REGION( 0x200000, "29f016a.27h", 0 ) /* onboard flash */
+	ROM_LOAD( "710uaa.27h",   0x000000, 0x200000, CRC(b30556bb) SHA1(b771114c6520fe17e4256b9217c72243ac97f4b5) )
+
+	ROM_REGION( 0x002000, "m48t58", 0 )
+	ROM_LOAD( "710uaa.22h",   0x000000, 0x002000, CRC(a3e93d49) SHA1(630daa1a02320433a068eb5214f6b30acc06df76) )
+ROM_END
+
 GAME( 1997, sys573,    0,        konami573,  konami573, driver_device, 0,        ROT0, "Konami", "System 573 BIOS", MACHINE_IS_BIOS_ROOT )
 
-GAME( 1997, hndlchmp,  sys573,   konami573,  hndlchmp,  driver_device, 0,        ROT0, "Konami", "Handle Champ (GQ710 VER. JAB)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND )
+GAME( 1997, strgchmp,  sys573,   konami573,  hndlchmp,  driver_device, 0,        ROT0, "Konami", "Steering Champ (GQ710 VER. UAA)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND )
+GAME( 1997, hndlchmp,  strgchmp, konami573,  hndlchmp,  driver_device, 0,        ROT0, "Konami", "Handle Champ (GQ710 VER. JAB)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND )
 GAME( 1998, darkhleg,  sys573,   konami573x, konami573, driver_device, 0,        ROT0, "Konami", "Dark Horse Legend (GX706 VER. JAA)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND )
 GAME( 1998, fbaitbc,   sys573,   fbaitbc,    fbaitbc,   driver_device, 0,        ROT0, "Konami", "Fisherman's Bait - A Bass Challenge (GE765 VER. UAB)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND )
 GAME( 1998, bassangl,  fbaitbc,  fbaitbc,    fbaitbc,   driver_device, 0,        ROT0, "Konami", "Bass Angler (GE765 VER. JAA)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND )
diff --git a/src/mame/drivers/ladybug.cpp b/src/mame/drivers/ladybug.cpp
index dc15d96..b8d00db 100644
--- a/src/mame/drivers/ladybug.cpp
+++ b/src/mame/drivers/ladybug.cpp
@@ -602,7 +602,7 @@ ROM_START( ladybugb )
 	ROM_LOAD( "10-3.c4", 0x0040, 0x0020, CRC(27fa3a50) SHA1(7cf59b7a37c156640d6ea91554d1c4276c1780e0) ) /* ?? */
 ROM_END
 
-ROM_START( ladybgb2 )
+ROM_START( ladybugb2 ) // bootleg by Model Racing, PCB marked CS299, manual names it "Coccinelle" (ladybugs in Italian)
 	ROM_REGION( 0x10000, "maincpu", 0 )
 	ROM_LOAD( "lb1b.cpu", 0x0000, 0x1000, CRC(35d61e65) SHA1(43b797f1882e0acbf6685deea82de77e78d2c917) )
 	ROM_LOAD( "lb2b.cpu", 0x1000, 0x1000, CRC(a13e0fe4) SHA1(9e2876d8390d2b072d064b197057089a25c13a4a) )
@@ -615,7 +615,7 @@ ROM_START( ladybgb2 )
 	ROM_LOAD( "l9.f7", 0x0000, 0x1000, CRC(77b1da1e) SHA1(58cb82417396a3d96acfc864f091b1a5988f228d) )
 	ROM_LOAD( "l0.h7", 0x1000, 0x1000, CRC(aa82e00b) SHA1(83a5b745e58844b6dd7d05dfe9dbb5959aaf5c40) )
 
-	ROM_REGION( 0x2000, "gfx2", 0 ) /* Located on the UNIVERSAL 8106-A2 CPU PCB */
+	ROM_REGION( 0x2000, "gfx2", 0 )
 	ROM_LOAD( "l8.l7", 0x0000, 0x1000, CRC(8b99910b) SHA1(0bc812cf872f04eacedb50feed53f1aa8a1f24b9) )
 	ROM_LOAD( "l7.m7", 0x1000, 0x1000, CRC(86a5b448) SHA1(f8585a6fcf921e3e21f112dd2de474cb53cef290) )
 
@@ -733,10 +733,10 @@ DRIVER_INIT_MEMBER(ladybug_state,dorodon)
 }
 
 
-GAME( 1981, cavenger, 0,       ladybug, cavenger, driver_device, 0,       ROT0,   "Universal", "Cosmic Avenger", MACHINE_SUPPORTS_SAVE )
-GAME( 1981, ladybug,  0,       ladybug, ladybug, driver_device,  0,       ROT270, "Universal", "Lady Bug", MACHINE_SUPPORTS_SAVE )
-GAME( 1981, ladybugb, ladybug, ladybug, ladybug, driver_device,  0,       ROT270, "bootleg",   "Lady Bug (bootleg set 1)", MACHINE_SUPPORTS_SAVE )
-GAME( 1981, ladybgb2, ladybug, ladybug, ladybug, driver_device,  0,       ROT270, "bootleg",   "Lady Bug (bootleg set 2)", MACHINE_SUPPORTS_SAVE )
-GAME( 1982, dorodon,  0,       dorodon, dorodon, ladybug_state,  dorodon, ROT270, "UPL (Falcon license?)", "Dorodon (set 1)", MACHINE_SUPPORTS_SAVE ) // license or bootleg?
-GAME( 1982, dorodon2, dorodon, dorodon, dorodon, ladybug_state,  dorodon, ROT270, "UPL (Falcon license?)", "Dorodon (set 2)", MACHINE_SUPPORTS_SAVE ) // "
-GAME( 1982, snapjack, 0,       ladybug, snapjack, driver_device, 0,       ROT0,   "Universal", "Snap Jack", MACHINE_SUPPORTS_SAVE )
+GAME( 1981, cavenger,  0,       ladybug, cavenger, driver_device, 0,       ROT0,   "Universal", "Cosmic Avenger", MACHINE_SUPPORTS_SAVE )
+GAME( 1981, ladybug,   0,       ladybug, ladybug, driver_device,  0,       ROT270, "Universal", "Lady Bug", MACHINE_SUPPORTS_SAVE )
+GAME( 1981, ladybugb,  ladybug, ladybug, ladybug, driver_device,  0,       ROT270, "bootleg",   "Lady Bug (bootleg set 1)", MACHINE_SUPPORTS_SAVE )
+GAME( 1981, ladybugb2, ladybug, ladybug, ladybug, driver_device,  0,       ROT270, "bootleg (Model Racing)", "Coccinelle (bootleg of Lady Bug, set 2)", MACHINE_SUPPORTS_SAVE ) // title removed, but manual names it Coccinelle
+GAME( 1982, dorodon,   0,       dorodon, dorodon, ladybug_state,  dorodon, ROT270, "UPL (Falcon license?)", "Dorodon (set 1)", MACHINE_SUPPORTS_SAVE ) // license or bootleg?
+GAME( 1982, dorodon2,  dorodon, dorodon, dorodon, ladybug_state,  dorodon, ROT270, "UPL (Falcon license?)", "Dorodon (set 2)", MACHINE_SUPPORTS_SAVE ) // "
+GAME( 1982, snapjack,  0,       ladybug, snapjack, driver_device, 0,       ROT0,   "Universal", "Snap Jack", MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/drivers/ladyfrog.cpp b/src/mame/drivers/ladyfrog.cpp
index 14cd8b2..2fadf53 100644
--- a/src/mame/drivers/ladyfrog.cpp
+++ b/src/mame/drivers/ladyfrog.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /*
 Lady Frog (c) 1990 Mondial Games
diff --git a/src/mame/drivers/laserbas.cpp b/src/mame/drivers/laserbas.cpp
index e4c6d38..b612920 100644
--- a/src/mame/drivers/laserbas.cpp
+++ b/src/mame/drivers/laserbas.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /********************************************
  Laser Base / Future Flash driver
diff --git a/src/mame/drivers/leland.cpp b/src/mame/drivers/leland.cpp
index 91e234c..b78bcad 100644
--- a/src/mame/drivers/leland.cpp
+++ b/src/mame/drivers/leland.cpp
@@ -60,9 +60,7 @@
 
 #include "emu.h"
 #include "includes/leland.h"
-#include "cpu/i86/i186.h"
 #include "cpu/z80/z80.h"
-#include "machine/eepromser.h"
 #include "machine/nvram.h"
 #include "sound/volt_reg.h"
 
@@ -2670,6 +2668,9 @@ DRIVER_INIT_MEMBER(leland_state,dangerz)
 	m_master->space(AS_IO).install_read_handler(0xf4, 0xf4, read8_delegate(FUNC(leland_state::dangerz_input_upper_r),this));
 	m_master->space(AS_IO).install_read_handler(0xf8, 0xf8, read8_delegate(FUNC(leland_state::dangerz_input_y_r),this));
 	m_master->space(AS_IO).install_read_handler(0xfc, 0xfc, read8_delegate(FUNC(leland_state::dangerz_input_x_r),this));
+
+	save_item(NAME(m_dangerz_x));
+	save_item(NAME(m_dangerz_y));
 }
 
 
@@ -2749,6 +2750,9 @@ DRIVER_INIT_MEMBER(leland_state,viper)
 	m_master->space(AS_IO).install_read_handler(0xa4, 0xa4, read8_delegate(FUNC(leland_state::dangerz_input_upper_r),this));
 	m_master->space(AS_IO).install_read_handler(0xb8, 0xb8, read8_delegate(FUNC(leland_state::dangerz_input_y_r),this));
 	m_master->space(AS_IO).install_read_handler(0xbc, 0xbc, read8_delegate(FUNC(leland_state::dangerz_input_x_r),this));
+
+	save_item(NAME(m_dangerz_x));
+	save_item(NAME(m_dangerz_y));
 }
 
 
diff --git a/src/mame/drivers/lwriter.cpp b/src/mame/drivers/lwriter.cpp
new file mode 100644
index 0000000..7cf4604
--- /dev/null
+++ b/src/mame/drivers/lwriter.cpp
@@ -0,0 +1,231 @@
+// license:BSD-3-Clause
+// copyright-holders:Joakim Larsson Edstrom
+/******************************************************************************
+
+    Apple LaserWriter II NT driver
+
+    TODO:
+    - Figure out what VIA pins is connected to switch on front that selects LocalTalk
+    - Let the board identify itself to a emulated mac driver so it displays the printer icon on the desktop
+    - Everything else
+
+******************************************************************************/
+/*
+ * Hardware: 68000 at 11.16 MHz
+             8530 SCC
+             6523 TPI or 6522 VIA on newer pcb:s
+             2MB DRAM
+             2KB SRAM
+             custom 335-0022 EEPROM
+             1MB ROM
+
+   +------------------------------------------------------------------------------------------------------------------------+=====+
+   |      1           2            3           4            5          6          7          8        9        10     11    |     #
+   |    +------+    +------+   +---------+                                                +-------+  +------+         +-+   |     #
+   |A   |511000|    | F257 |   |335-0022 |                                                | 0296  |  |22.3210         | | J2|     #
+   |    +------+    +------+   |EEPROM   |                     +-------+                  +-------+  |XTAL  |         | |   |     #
+   |B   |511000|    | RP2B |   +---------+                     |       |                             +------+         | |   |     #
+   |    +------+    +------+                                   | 68000 |                  +-------+  +-------+        +-+   |     #
+   |C   |511000|    | F257 |                                   |       |                  | 0558  |  | F175  |        +-+   |     #
+   |    +------+    +------+   +---------+                     |       |                  +-------+  +-------+        | |   |     #
+   |D   |511000|    +------+   |Am9128-10|                     |       |        +-------+ +-------+  +-------+        | |   |     #
+   |    +------+    | F257 |   |SRAM     |                     |       |        | 0559  | | 0557  |  | LS393 |        | |   |     #
+   |E   |511000|    +------+   +---------+                     |       |        +-------+ +-------+  +-------+        +-+   |  F  #
+   |    +------+    +------+   +---------+                     |       |                                      +------+      |     #
+   |F   |511000|    | F138 |   |Am9128-10|                     |       |                +-----------------+   |26LS32|    J3|  R  #
+   |    +------+    +------+   |SRAM     |                     |       |                | Z8530B1C        |   +------+      |     #
+   |G   |511000|               +--------++                     |       |                | SCC             |   |26LS32|      |  O  #
+   |    +------+    +------+   | F244   |                      |       |     +----+     +-----------------+   +------+      |     #
+   |H   |511000|    | RP2H |   +--------+                      +-------+     |7705|                           +------+      |  N  #
+   |    +------+    +------+   | F244   |                                    +----+     +-----------------+   |26LS30|      |     #
+   |J   |511000|    | 0259 |   +--------+-+----------+                   o------o       | 338-6523        |   +------+      |  T  #
+   |    +------+    +------+   | TC531000 | TC531000 |                   | CONN |       | TPI             |   |26LS30|      |     #
+   |K   |511000|    +------+   |  ROM H3  |  ROM L3  |          +------+ |   == |       +-----------------+   +------+      |     #
+   |    +------+    | RP2L |   +----------+----------+          | F02  | |   == |             +-------+                     |     #
+   |L   |511000|    +------+   +----------+----------+          +------+ |   == |             | LS14  |                     |     #
+   |    +------+    | 0259 |   | TC531000 | TC531000 |  +------++------+ |   == |             +-------+                     |     #
+   |M   |511000|    +------+   |  ROM H2  |  ROM L2  |  |67L401|| LS166| |   == |             | LS14  |                     |     #
+   |    +------+    +------+   +----------+----------+  +------++------+ |   == |             +-------+ +------+            |     #
+   |N   |511000|    | F245 |   +----------+----------+  +------++------+ |   == |                       | 0440A|            |     #
+   |    +------+    +------+   | TC531000 | TC531000 |  |67L401|| LS00 | |   == |                       +------+            |     #
+   |P   |511000|    +------+   |  ROM H1  |  ROM L1  |  +------++------+ o------o      +------+                             |     #
+   |    +------+    | F245 |   +----------+----------+         +-------+               |TL497 |                             |     #
+   |R   |511000|    +------+   +----------+----------+         | LS273 |               +------+                             |     #
+   |    +------+    +------+   | TC531000 | TC531000 |         +-------+                                                    |     #
+   |S   |511000|    | RP2S |   |  ROM H0  |  ROM L0  |         | LS05 |                                                     |     #
+   |    +------+    +------+   +----------+----------+         +------+  (c)1987                                          J4|     #
+   |     DRAM                       LASERWRITER II NT                    Apple Computer               640-4105              |     #
+   +------------------------------------------------------------------------------------------------------------------------+=====+
+ */
+
+#define TPI 0  //The TPI is used on the original M6009 board but the first dump is from a newer that uses a VIA
+
+#include "emu.h"
+#include "cpu/m68000/m68000.h"
+#include "bus/rs232/rs232.h"
+#include "machine/z80scc.h"
+
+#if TPI
+#include "machine/6525tpi.h"
+#else
+#include "machine/6522via.h"
+#endif
+
+class lwriter_state : public driver_device
+{
+public:
+	lwriter_state(const machine_config &mconfig, device_type type, const char *tag)
+		: driver_device(mconfig, type, tag)
+		, m_maincpu(*this, "maincpu")
+		, m_scc(*this, "scc")
+		, m_via(*this, "via")
+	{ }
+	DECLARE_READ16_MEMBER (bootvect_r);
+	DECLARE_WRITE16_MEMBER (bootvect_w);
+	virtual void machine_start () override;
+	virtual void machine_reset () override;
+private:
+	required_device<cpu_device> m_maincpu;
+	required_device<scc8530_device> m_scc;
+
+#if TPI
+#define tpi6523_device tpi6525_device/* TODO: define a type for the TPI6523 of its own in the device header file */
+	required_device<tpi6523_device> m_tpi;
+#else
+	required_device<via6522_device> m_via;
+#endif
+
+	// Pointer to System ROMs needed by bootvect_r and masking RAM buffer for post reset accesses
+	uint16_t  *m_sysrom;
+	uint16_t  m_sysram[2];
+};
+
+static ADDRESS_MAP_START (maincpu_map, AS_PROGRAM, 16, lwriter_state)
+	ADDRESS_MAP_UNMAP_HIGH
+	AM_RANGE(0x00000000, 0x00000007) AM_ROM AM_READ(bootvect_r) /* ROM mirror just during reset */
+	AM_RANGE(0x00000000, 0x00000007) AM_RAM AM_WRITE(bootvect_w) /* After first write we act as RAM */
+	AM_RANGE(0x00000008, 0x001fffff) AM_RAM /* 2 Mb DRAM */
+	AM_RANGE(0x00200000, 0x003fffff) AM_ROM AM_REGION("roms", 0)
+
+	AM_RANGE(0x00c00000, 0x00c00001) AM_DEVWRITE8("scc", scc8530_device, ca_w, 0x00ff)
+	AM_RANGE(0x00c00004, 0x00c00005) AM_DEVWRITE8("scc", scc8530_device, da_w, 0x00ff)
+	AM_RANGE(0x00a00000, 0x00a00001) AM_DEVREAD8 ("scc", scc8530_device, ca_r, 0xff00)
+	AM_RANGE(0x00a00004, 0x00a00005) AM_DEVREAD8 ("scc", scc8530_device, da_r, 0xff00)
+
+	AM_RANGE(0x00c00002, 0x00c00003) AM_DEVWRITE8("scc", scc8530_device, cb_w, 0x00ff)
+	AM_RANGE(0x00c00006, 0x00c00007) AM_DEVWRITE8("scc", scc8530_device, db_w, 0x00ff)
+	AM_RANGE(0x00a00002, 0x00a00003) AM_DEVREAD8 ("scc", scc8530_device, cb_r, 0xff00)
+	AM_RANGE(0x00a00006, 0x00a00007) AM_DEVREAD8 ("scc", scc8530_device, db_r, 0xff00)
+
+#if TPI
+	AM_RANGE(0x00e00010, 0x00e0001f) AM_DEVREADWRITE8 ("tpi", tpi6523_device, read, write, 0x00ff) // Used on older boards, needs proper mapping
+#else
+	AM_RANGE(0x00e00000, 0x00e0001f) AM_DEVREADWRITE8 ("via", via6522_device, read, write, 0x00ff)
+#endif
+ADDRESS_MAP_END
+
+static INPUT_PORTS_START( lwriter )
+INPUT_PORTS_END
+
+/* Start it up */
+void lwriter_state::machine_start()
+{
+	/* Setup pointer to bootvector in ROM for bootvector handler bootvect_r */
+	m_sysrom = (uint16_t*)(memregion ("roms")->base ());
+}
+
+void lwriter_state::machine_reset ()
+{
+	/* Reset pointer to bootvector in ROM for bootvector handler bootvect_r */
+	if (m_sysrom == &m_sysram[0]) /* Condition needed because memory map is not setup first time */
+		m_sysrom = (uint16_t*)(memregion ("roms")->base ());
+}
+
+/* Boot vector handler, the PCB hardwires the first 8 bytes from 0xff800000 to 0x0 at reset*/
+READ16_MEMBER (lwriter_state::bootvect_r){
+	return m_sysrom[offset];
+}
+
+WRITE16_MEMBER (lwriter_state::bootvect_w){
+	m_sysram[offset % sizeof(m_sysram)] &= ~mem_mask;
+	m_sysram[offset % sizeof(m_sysram)] |= (data & mem_mask);
+	m_sysrom = &m_sysram[0]; // redirect all upcomming accesses to masking RAM until reset.
+}
+
+#define CPU_CLK (XTAL_22_3210MHz / 2) // Based on pictures form here: http://picclick.co.uk/Apple-Postscript-LaserWriter-IINT-Printer-640-4105-M6009-Mainboard-282160713108.html#&gid=1&pid=7
+#define RXC_CLK ((CPU_CLK - (87 * 16 * 70)) / 3) // Tuned to get 9600 baud according to manual, needs rework based on real hardware
+
+static MACHINE_CONFIG_START( lwriter, lwriter_state )
+	MCFG_CPU_ADD("maincpu", M68000, CPU_CLK)
+	MCFG_CPU_PROGRAM_MAP(maincpu_map)
+	MCFG_SCC8530_ADD("scc", CPU_CLK, RXC_CLK, 0, RXC_CLK, 0)
+	/* Port A */
+	MCFG_Z80SCC_OUT_TXDA_CB(DEVWRITELINE("rs232a", rs232_port_device, write_txd))
+	MCFG_Z80SCC_OUT_DTRA_CB(DEVWRITELINE("rs232a", rs232_port_device, write_dtr))
+	MCFG_Z80SCC_OUT_RTSA_CB(DEVWRITELINE("rs232a", rs232_port_device, write_rts))
+	/* Port B */
+	MCFG_Z80SCC_OUT_TXDB_CB(DEVWRITELINE("rs232b", rs232_port_device, write_txd))
+	MCFG_Z80SCC_OUT_DTRB_CB(DEVWRITELINE("rs232b", rs232_port_device, write_dtr))
+	MCFG_Z80SCC_OUT_RTSB_CB(DEVWRITELINE("rs232b", rs232_port_device, write_rts))
+
+	MCFG_RS232_PORT_ADD ("rs232a", default_rs232_devices, "terminal")
+	MCFG_RS232_RXD_HANDLER (DEVWRITELINE ("scc", scc8530_device, rxa_w))
+	MCFG_RS232_CTS_HANDLER (DEVWRITELINE ("scc", scc8530_device, ctsa_w))
+
+	MCFG_RS232_PORT_ADD ("rs232b", default_rs232_devices, "terminal")
+	MCFG_RS232_RXD_HANDLER (DEVWRITELINE ("scc", scc8530_device, rxb_w))
+	MCFG_RS232_CTS_HANDLER (DEVWRITELINE ("scc", scc8530_device, ctsb_w))
+
+#if TPI
+	MCFG_DEVICE_ADD("tpi", TPI6525, 0)
+#else
+	MCFG_DEVICE_ADD("via", VIA6522, 0)
+#endif
+MACHINE_CONFIG_END
+
+/* SCC init sequence
+ * :scc B Reg 09 <- c0 - Master Interrupt Control - Device reset
+ * -
+ * :scc A Reg 0f <- 00 - External/Status Control Bits - Disable all
+ * :scc B Reg 05 <- 02 - Tx setup: 5 bits, Tx disable, RTS:1 DTR:0
+ * :scc B Reg 05 <- 00 - Tx setup: 5 bits, Tx disable, RTS:0 DTR:0
+ * -
+ * :scc A Reg 09 <- c0 - Master Interrupt Control - Device reset
+ *
+ * -
+ * :scc A Reg 0f <- 00 - External/Status Control Bits - Disable all
+ * :scc A Reg 04 <- 4c - Setting up Asynchrounous mode: 2 Stop bits, No parity, 16x clock
+ * :scc A Reg 0b <- 50 - Clock Mode Control - TTL clk on RTxC, Rx and Tx clks from BRG, TRxC is input
+ * :scc A Reg 0e <- 00 - Misc Control Bits - BRG clk is RTxC, BRG is disabled
+ * :scc A Reg 0c <- 0a - Low byte of baudrate generator constant
+ * :scc A Reg 0d <- 00 - Hi byte of baudrate generator constant
+ * :scc A Reg 0e <- 01 - BRG enabled with external clk from RTxC
+ * :scc A Reg 0a <- 00 - Synchronous parameters, all turned off
+ * :scc A Reg 03 <- c1 - Rx setup: 8 bits, Rx enabled
+ * :scc A Reg 05 <- 6a - Tx setup: 8 bits, Tx enable, RTS:1 DTR:0
+ * -
+ * :scc A Reg 01 <- 00 - Rx interrupt disabled
+ * :scc A Reg 01 <- 30 - Wait/Ready on receive, Rx int an all characters, parity affect vector
+ * :scc A Reg 00 <- 30 - Error Reset command
+ * -
+ * :scc A Reg 01 <- 01 - External interrupt enabled, Rx ints disabled
+ * :scc A Reg 00 <- 30 - Error Reset command
+ * :scc A Reg 00 <- 30 - Error Reset command
+ * - last three loops
+*/
+
+ROM_START(lwriter)
+	ROM_REGION16_BE (0x1000000, "roms", 0)
+
+	ROM_LOAD16_BYTE ("342-0545.l0", 0x000001, 0x20000, CRC (6431742d) SHA1 (040bd5b84b49b86f2b0fe9ece378bbc7a10a94ec))
+	ROM_LOAD16_BYTE ("342-0546.h0", 0x000000, 0x20000, CRC (c592bfb7) SHA1 (b595ae225238f7fabd1566a3133ea6154e082e2d))
+	ROM_LOAD16_BYTE ("342-0547.l1", 0x040001, 0x20000, CRC (205a5ea8) SHA1 (205fefbb5c67a07d57cb6184c69648321a34a8fe))
+	ROM_LOAD16_BYTE ("342-0548.h1", 0x040000, 0x20000, CRC (f616e1c3) SHA1 (b9e2cd4d07990b2d1936be97b6e89ef21f06b462))
+	ROM_LOAD16_BYTE ("342-0549.l2", 0x080001, 0x20000, CRC (0b0b051a) SHA1 (64a80085001570c3f99d9865031715bf49bd7698))
+	ROM_LOAD16_BYTE ("342-0550.h2", 0x080000, 0x20000, CRC (82adcf85) SHA1 (e2ab728afdae802c0c67fc25c9ba278b9cb04e31))
+	ROM_LOAD16_BYTE ("342-0551.l3", 0x0c0001, 0x20000, CRC (176b3346) SHA1 (eb8dfc7e44f2bc884097e51a47e2f10ee091c9e9))
+	ROM_LOAD16_BYTE ("342-0552.h3", 0x0c0000, 0x20000, CRC (69b175c6) SHA1 (a84c82be1ec7e373bb097ee74b941920a3b091aa))
+ROM_END
+
+/*    YEAR  NAME        PARENT    COMPAT  MACHINE    INPUT      INIT,             COMPANY,                FULLNAME,                   FLAGS */
+CONS( 1988, lwriter,    0,        0,      lwriter,   lwriter,   driver_device, 0, "Apple",                "Apple Laser Writer II NT", MACHINE_IS_SKELETON)
diff --git a/src/mame/drivers/mac128.cpp b/src/mame/drivers/mac128.cpp
old mode 100755
new mode 100644
index e11648e..44aa12d
--- a/src/mame/drivers/mac128.cpp
+++ b/src/mame/drivers/mac128.cpp
@@ -1517,13 +1517,32 @@ ROM_START( mac128k )
 	ROM_REGION16_BE(0x100000, "bootrom", 0)
 	// Apple used at least 3 manufacturers for these ROMs, but they're always Apple part numbers 342-0220-A and 342-0221-A
 	ROMX_LOAD("342-0220-a.u6d",  0x00000, 0x08000, CRC(198210ad) SHA1(2590ff4af5ac0361babdf0dc5da18e2eecad454a), ROM_SKIP(1) )
- 	ROMX_LOAD("342-0221-a.u8d",  0x00001, 0x08000, CRC(fd2665c2) SHA1(8507932a854bd28196a17785c8b1851cb53eaf64), ROM_SKIP(1) )
+	ROMX_LOAD("342-0221-a.u8d",  0x00001, 0x08000, CRC(fd2665c2) SHA1(8507932a854bd28196a17785c8b1851cb53eaf64), ROM_SKIP(1) )
+	/* Labels seen in the wild:
+	VTi:
+	"<VTi logo along side> // 416 VH 2605 // 23256-1020 // 342-0220-A // (C)APPLE 83 // KOREA-AE"
+	"<VTi logo along side> // 416 VH 2826 // 23256-1023 // 342-0221-A // (C)APPLE 83 // KOREA-AE"
+	Synertek:
+	"<Synertek 'S' logo> 8416 G // C19728 // 342-0220-A // (C)APPLE 83"
+	"<Synertek 'S' logo> 8410 G // C19729 // 342-0221-A // (C)APPLE 83"
+	Hitachi:
+	[can't find reference for rom-hi]
+	"<Hitachi 'target' logo> 8413 // 3256 016 JAPAN // (C)APPLE 83 // 342-0221-A"
+
+	References:
+	http://www.vintagecomputer.net/apple/Macintosh/Macintosh_motherboard.jpg
+	https://upload.wikimedia.org/wikipedia/commons/3/34/Macintosh-motherboard.jpg
+	https://68kmla.org/forums/uploads/monthly_01_2016/post-2105-0-31195100-1452296677.jpg
+	https://68kmla.org/forums/uploads/monthly_12_2014/post-2597-0-46269000-1419299800.jpg
+	http://cdn.cultofmac.com/wp-content/uploads/2014/01/12A-128k-Motherboard.jpg
+	*/
 ROM_END
 
 ROM_START( mac512k )
 	ROM_REGION16_BE(0x100000, "bootrom", 0)
 	ROMX_LOAD("342-0220-b.u6d",  0x00000, 0x08000, CRC(0dce9a3f) SHA1(101ca6570f5a273e400d1a8bc63e15ee0e94153e), ROM_SKIP(1) ) // "<VTi logo along side> 512 VH 6434 // 23256-1104 // 342-0220-B // (C) APPLE 84 // KOREA-A"
 	ROMX_LOAD("342-0221-b.u8d",  0x00001, 0x08000, CRC(d51f376e) SHA1(575586109e876cffa4a4d472cb38771aa21b70cb), ROM_SKIP(1) ) // "<VTi logo along side> 512 VH 6709 // 23256-1105 // 342-0221-B // (C) APPLE 84 // KOREA-A"
+	// reference: http://i.ebayimg.com/images/g/Uj8AAOSwvzRXy2tW/s-l1600.jpg
 ROM_END
 
 ROM_START( unitron )
@@ -1573,39 +1592,69 @@ ROM_END
  * 0f <- 88 External/Status Control: Abort/Break and DCD interrupts enabled
 */
 
-ROM_START( mac512ke )
+ROM_START( mac512ke ) // 512ke has been observed with any of the v3, v2 or v1 macplus romsets installed, and v1 romsets are more common here than in the plus, since the 512ke lacks scsi, which is the cause of the major bug fixed between v1 and v2, hence 512ke is unaffected and was a good way for apple to use up the buggy roms rather than destroying them.
 	ROM_REGION16_BE(0x100000, "bootrom", 0)
-	ROM_SYSTEM_BIOS(0, "v3", "Loud Harmonicas") // AMI and VLSI manufacture
+	ROM_SYSTEM_BIOS(0, "v3", "Loud Harmonicas")
 	ROMX_LOAD( "342-0341-c.u6d", 0x000000, 0x010000, CRC(f69697e6) SHA1(41317614ac71eb94941e9952f6ea37407e21ffff), ROM_SKIP(1) | ROM_BIOS(1) )
 	ROMX_LOAD( "342-0342-b.u8d", 0x000001, 0x010000, CRC(49f25913) SHA1(72f658c02bae265e8845899582575fb7c784ee87), ROM_SKIP(1) | ROM_BIOS(1) )
 	ROM_FILL(0x20000, 0x2, 0xff)    // ROM checks for same contents at 20000 and 40000 to determine if SCSI is present
 	ROM_FILL(0x40000, 0x2, 0xaa)
-	ROM_SYSTEM_BIOS(1, "v2", "Lonely Heifers") // VTi manufacture
+	ROM_SYSTEM_BIOS(1, "v2", "Lonely Heifers")
 	ROMX_LOAD( "342-0341-b.u6d", 0x000000, 0x010000, CRC(65341487) SHA1(bf43fa4f5a3dcbbac20f1fe1deedee0895454379), ROM_SKIP(1) | ROM_BIOS(2) )
 	ROMX_LOAD( "342-0342-a.u8d", 0x000001, 0x010000, CRC(fb766270) SHA1(679f529fbfc05f9cc98924c53457d2996dfcb1a7), ROM_SKIP(1) | ROM_BIOS(2) )
 	ROM_FILL(0x20000, 0x2, 0xff)
 	ROM_FILL(0x40000, 0x2, 0xaa)
-	ROM_SYSTEM_BIOS(2, "v1", "Lonely Hearts") // VTi manufacture
+	ROM_SYSTEM_BIOS(2, "v1", "Lonely Hearts")
 	ROMX_LOAD( "342-0341-a.u6d", 0x000000, 0x010000, CRC(5095fe39) SHA1(be780580033d914b5035d60b5ebbd66bd1d28a9b), ROM_SKIP(1) | ROM_BIOS(3) )
 	ROMX_LOAD( "342-0342-a.u8d", 0x000001, 0x010000, CRC(fb766270) SHA1(679f529fbfc05f9cc98924c53457d2996dfcb1a7), ROM_SKIP(1) | ROM_BIOS(3) )
 	ROM_FILL(0x20000, 0x2, 0xff)
 	ROM_FILL(0x40000, 0x2, 0xaa)
+	/* from Technical note HW11 (https://www.fenestrated.net/mirrors/Apple%20Technotes%20(As%20of%202002)/hw/hw_11.html)
+	1st version (Lonely Hearts, checksum 4D 1E EE E1)
+	Bug in the SCSI driver; won't boot if external drive is turned off. We only produced about
+	one and a half months worth of these.
+
+	2nd version (Lonely Heifers, checksum 4D 1E EA E1):
+	Fixed boot bug. This version is the vast majority of beige Macintosh Pluses.
+
+	3rd version (Loud Harmonicas, checksum 4D 1F 81 72):
+	Fixed bug for drives that return Unit Attention on power up or reset. Basically took the
+	SCSI bus Reset command out of the boot sequence loop, so it will only reset once
+	during boot sequence.
+	*/
+	/* Labels seen in the wild:
+	v3/4d1f8172:
+	    'ROM-HI' @ U6D:
+	        "VLSI // 740 SA 1262 // 23512-1054 // 342-0341-C // (C)APPLE '83-'86 // KOREA A"
+	        "342-0341-C // (C)APPLE 85,86 // (M)AMI 8849MBL // PHILLIPINES"
+	    'ROM-LO' @ U8D:
+	        "VLSI // 740 SA 1342 // 23512-1055 // 342-0342-B // (C)APPLE '83-'86 // KOREA A"
+	        "<VLSI logo>VLSI // 8905AV 0 AS759 // 23512-1055 // 342-0342-B // (C)APPLE '85-'86"
+	v2/4d1eeae1:
+	    'ROM-HI' @ U6D:
+	        "VTI // 624 V0 8636 // 23512-1010 // 342-0341-B // (C)APPLE '85 // MEXICO R"
+	    'ROM-LO' @ U8D:
+	        "VTI // 622 V0 B637 // 23512-1007 // 342-0342-A // (C)APPLE '83-'85 // KOREA A"
+	v1/4d1eeee1:
+	    'ROM-HI' @ U6D:
+	        GUESSED, since this ROM is very rare: "VTI // 62? V0 86?? // 23512-1008 // 342-0341-A // (C)APPLE '83-'85 // KOREA A"
+	    'ROM-LO' @ U8D is same as v2/4d1eeae1 'ROM-LO' @ U8D
+	*/
 ROM_END
 
-
-ROM_START( macplus )
+ROM_START( macplus ) // same notes as above apply here as well
 	ROM_REGION16_BE(0x100000, "bootrom", 0)
-	ROM_SYSTEM_BIOS(0, "v3", "Loud Harmonicas") // AMI and VLSI manufacture
+	ROM_SYSTEM_BIOS(0, "v3", "Loud Harmonicas")
 	ROMX_LOAD( "342-0341-c.u6d", 0x000000, 0x010000, CRC(f69697e6) SHA1(41317614ac71eb94941e9952f6ea37407e21ffff), ROM_SKIP(1) | ROM_BIOS(1) )
 	ROMX_LOAD( "342-0342-b.u8d", 0x000001, 0x010000, CRC(49f25913) SHA1(72f658c02bae265e8845899582575fb7c784ee87), ROM_SKIP(1) | ROM_BIOS(1) )
 	ROM_FILL(0x20000, 0x2, 0xff)    // ROM checks for same contents at 20000 and 40000 to determine if SCSI is present
 	ROM_FILL(0x40000, 0x2, 0xaa)
-	ROM_SYSTEM_BIOS(1, "v2", "Lonely Heifers") // VTi manufacture
+	ROM_SYSTEM_BIOS(1, "v2", "Lonely Heifers")
 	ROMX_LOAD( "342-0341-b.u6d", 0x000000, 0x010000, CRC(65341487) SHA1(bf43fa4f5a3dcbbac20f1fe1deedee0895454379), ROM_SKIP(1) | ROM_BIOS(2) )
 	ROMX_LOAD( "342-0342-a.u8d", 0x000001, 0x010000, CRC(fb766270) SHA1(679f529fbfc05f9cc98924c53457d2996dfcb1a7), ROM_SKIP(1) | ROM_BIOS(2) )
 	ROM_FILL(0x20000, 0x2, 0xff)
 	ROM_FILL(0x40000, 0x2, 0xaa)
-	ROM_SYSTEM_BIOS(2, "v1", "Lonely Hearts") // VTi manufacture
+	ROM_SYSTEM_BIOS(2, "v1", "Lonely Hearts")
 	ROMX_LOAD( "342-0341-a.u6d", 0x000000, 0x010000, CRC(5095fe39) SHA1(be780580033d914b5035d60b5ebbd66bd1d28a9b), ROM_SKIP(1) | ROM_BIOS(3) )
 	ROMX_LOAD( "342-0342-a.u8d", 0x000001, 0x010000, CRC(fb766270) SHA1(679f529fbfc05f9cc98924c53457d2996dfcb1a7), ROM_SKIP(1) | ROM_BIOS(3) )
 	ROM_FILL(0x20000, 0x2, 0xff)
diff --git a/src/mame/drivers/magnum.cpp b/src/mame/drivers/magnum.cpp
new file mode 100644
index 0000000..b59e992
--- /dev/null
+++ b/src/mame/drivers/magnum.cpp
@@ -0,0 +1,182 @@
+// license:BSD-3-Clause
+// copyright-holders:Carl
+
+// Dulmont Magnum
+// Additional info https://www.youtube.com/watch?v=st7H_vqSaQc and
+// http://www.eevblog.com/forum/blog/eevblog-949-vintage-australian-made-laptop-teardown/msg1080508/#msg1080508
+
+#include "emu.h"
+#include "rendlay.h"
+#include "cpu/i86/i186.h"
+#include "machine/cdp1879.h"
+#include "sound/beep.h"
+
+class magnum_state : public driver_device
+{
+public:
+	magnum_state(const machine_config &mconfig, device_type type, const char *tag) :
+	driver_device(mconfig, type, tag),
+	m_palette(*this, "palette"),
+	m_cgrom(*this, "cgrom"),
+	m_beep(*this, "beep")
+	{}
+
+	DECLARE_READ8_MEMBER(lcd_r);
+	DECLARE_WRITE8_MEMBER(lcd_w);
+	DECLARE_WRITE8_MEMBER(beep_w);
+	u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+protected:
+	virtual void machine_reset() override;
+	virtual void machine_start() override;
+private:
+	required_device<palette_device> m_palette;
+	required_memory_region m_cgrom;
+	required_device<beep_device> m_beep;
+
+	struct lcd
+	{
+		u8 vram[640];
+		u8 cmd;
+		u16 cursor;
+	};
+	lcd m_lcd[2];
+};
+
+u32 magnum_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+	u8* font = m_cgrom->base();
+	u32 black = m_palette->pen(0);
+	u32 white = m_palette->pen(1);
+	for(int scr = 0; scr < 2; scr++)
+	{
+		u8* vram = m_lcd[!scr].vram;
+		for(int i = 0; i < 16; i++)
+		{
+			for(int j = 0; j < 40; j++)
+			{
+				for(int k = 0; k < 9; k++)
+				{
+					for(int l = 0; l < 6; l++)
+						bitmap.pix32((i * 9) + k, ((j + (scr * 40)) * 6) + l) = font[(vram[(i * 40) + j] * 16) + k] & (1 << (5 - l)) ? black : white;
+				}
+			}
+		}
+	}
+	return 0;
+}
+
+void magnum_state::machine_start()
+{
+	save_item(NAME(m_lcd[0].vram));
+	save_item(NAME(m_lcd[0].cmd));
+	save_item(NAME(m_lcd[0].cursor));
+	save_item(NAME(m_lcd[1].vram));
+	save_item(NAME(m_lcd[1].cmd));
+	save_item(NAME(m_lcd[1].cursor));
+}
+
+void magnum_state::machine_reset()
+{
+	memset(m_lcd, 0, sizeof(m_lcd));
+}
+
+READ8_MEMBER(magnum_state::lcd_r)
+{
+	//lcd& panel = m_lcd[BIT(offset, 1)];
+	switch(BIT(offset, 0))
+	{
+		case 1:
+			return 0; // bit 8 busy status
+	}
+	return 0;
+}
+
+WRITE8_MEMBER(magnum_state::lcd_w)
+{
+	lcd& panel = m_lcd[BIT(offset, 1)];
+	switch(BIT(offset, 0))
+	{
+		case 0:
+			switch(panel.cmd)
+			{
+				case 0xa:
+					panel.cursor = ((panel.cursor & 0xff00) | data) % 640;
+					break;
+				case 0xb:
+					panel.cursor = ((panel.cursor & 0x00ff) | (data << 8)) % 640;
+					break;
+				case 0xc:
+					panel.vram[panel.cursor] = data;
+					panel.cursor++;
+					panel.cursor %= 640;
+					break;
+			}
+			break;
+		case 1:
+			panel.cmd = data;
+			break;
+	}
+}
+
+WRITE8_MEMBER(magnum_state::beep_w)
+{
+	if (data & ~1) printf("beep_w unmapped bits %02x\n", data);
+	m_beep->set_state(BIT(data, 0));
+}
+
+static ADDRESS_MAP_START( magnum_map, AS_PROGRAM, 16, magnum_state )
+	AM_RANGE(0x00000, 0x3ffff) AM_RAM // fixed 256k for now
+	AM_RANGE(0xe0000, 0xfffff) AM_ROM AM_REGION("bios", 0)
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( magnum_io, AS_IO, 16, magnum_state )
+	ADDRESS_MAP_UNMAP_HIGH
+	//AM_RANGE(0x000a, 0x000b) cdp1854 1
+	//AM_RANGE(0x000e, 0x000f) cpd1854 2
+	AM_RANGE(0x0018, 0x001f) AM_READWRITE8(lcd_r, lcd_w, 0x00ff)
+	AM_RANGE(0x0056, 0x0057) AM_WRITE8(beep_w, 0x00ff)
+	AM_RANGE(0x0080, 0x008f) AM_DEVREADWRITE8("rtc", cdp1879_device, read, write, 0x00ff)
+ADDRESS_MAP_END
+
+static MACHINE_CONFIG_START( magnum, magnum_state )
+	MCFG_CPU_ADD("maincpu", I80186, XTAL_12MHz / 2)
+	MCFG_CPU_PROGRAM_MAP(magnum_map)
+	MCFG_CPU_IO_MAP(magnum_io)
+
+	MCFG_DEVICE_ADD("rtc", CDP1879, XTAL_32_768kHz)
+
+	MCFG_SCREEN_ADD("screen", LCD)
+	MCFG_SCREEN_UPDATE_DRIVER(magnum_state, screen_update)
+	MCFG_SCREEN_REFRESH_RATE(50)
+	MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */
+	MCFG_SCREEN_SIZE(6*80, 9*16)
+	MCFG_SCREEN_VISIBLE_AREA(0, 6*80-1, 0, 9*16-1)
+
+	MCFG_DEFAULT_LAYOUT(layout_lcd)
+
+	MCFG_PALETTE_ADD_MONOCHROME("palette")
+
+	MCFG_SPEAKER_STANDARD_MONO("speaker")
+	MCFG_SOUND_ADD("beep", BEEP, 500) /// frequency is guessed
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "speaker", 0.50)
+MACHINE_CONFIG_END
+
+ROM_START( magnum )
+	ROM_REGION(0x20000, "bios", 0)
+	ROM_LOAD16_BYTE("a1.7.88.bin", 0x00000, 0x4000, CRC(57882427) SHA1(97637b65ca43eb9d3bba546fb8ca701ba25ade8d))
+	ROM_LOAD16_BYTE("a1.7.81.bin", 0x00001, 0x4000, CRC(949f53a8) SHA1(b339f1495d9af7dfff0c3a2c24789631f9d1265b))
+	ROM_LOAD16_BYTE("a1.7.87.bin", 0x08000, 0x4000, CRC(25036dda) SHA1(20bc3782a66855b20cb0abe1051fa2eb50c7a860))
+	ROM_LOAD16_BYTE("a1.7.82.bin", 0x08001, 0x4000, CRC(ecf387d8) SHA1(8b42f6ab030afb51f21f4a56c62e5acf7d074066))
+	ROM_LOAD16_BYTE("a1.7.86.bin", 0x10000, 0x4000, CRC(c80b3a6b) SHA1(0f0d2cb653bbeff8f3bab6d20dc30c220a67a315))
+	ROM_LOAD16_BYTE("a1.7.83.bin", 0x10001, 0x4000, CRC(51f56d78) SHA1(df717eada5e6439b1c01d91bd0ea009cd0f8ddfa))
+	ROM_LOAD16_BYTE("a1.7.85.bin", 0x18000, 0x4000, CRC(f5dd5407) SHA1(af2edf7a658bcf648acb8be9f13849f838d96214))
+	ROM_LOAD16_BYTE("a1.7.84.bin", 0x18001, 0x4000, CRC(b3434bb0) SHA1(8000a7aca8fc505b136a618d9eb210c50393eff1))
+
+	ROM_REGION(0x1000, "char", 0)
+	ROM_LOAD("dulmontcharrom.bin", 0x0000, 0x1000, CRC(9dff89bf) SHA1(d359aeba7f0b0c81accf3bca25e7da636c033721))
+
+	ROM_REGION(0x1000, "cgrom", 0) // borrow this rom for the lcd screen as it looks the same, the above is for the crt output
+	ROM_LOAD("hd44780_a00.bin", 0x0000, 0x1000,  BAD_DUMP CRC(01d108e2) SHA1(bc0cdf0c9ba895f22e183c7bd35a3f655f2ca96f))
+ROM_END
+
+COMP( 1983, magnum, 0, 0, magnum, 0, driver_device, 0, "Dulmont", "Magnum", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
diff --git a/src/mame/drivers/mc1000.cpp b/src/mame/drivers/mc1000.cpp
index 7735c31..85a7d67 100644
--- a/src/mame/drivers/mc1000.cpp
+++ b/src/mame/drivers/mc1000.cpp
@@ -77,6 +77,8 @@ public:
 	required_ioport m_modifiers;
 	required_ioport_array<2> m_joykeymap;
 
+	std::unique_ptr<uint8_t[]> m_banked_ram;
+
 	virtual void machine_start() override;
 	virtual void machine_reset() override;
 
@@ -89,7 +91,7 @@ public:
 	DECLARE_READ8_MEMBER( videoram_r );
 	DECLARE_WRITE8_MEMBER( keylatch_w );
 	DECLARE_READ8_MEMBER( keydata_r );
-	DIRECT_UPDATE_MEMBER(mc1000_direct_update_handler);
+	DECLARE_READ8_MEMBER( rom_banking_r );
 
 	void bankswitch();
 
@@ -223,11 +225,21 @@ WRITE8_MEMBER( mc1000_state::mc6847_attr_w )
 static ADDRESS_MAP_START( mc1000_mem, AS_PROGRAM, 8, mc1000_state )
 	AM_RANGE(0x0000, 0x1fff) AM_RAMBANK("bank1")
 	AM_RANGE(0x2000, 0x27ff) AM_RAMBANK("bank2") AM_SHARE("mc6845_vram")
-	AM_RANGE(0x2800, 0x3fff) AM_RAM
+	AM_RANGE(0x2800, 0x3fff) AM_RAM AM_SHARE("ram2800")
 	AM_RANGE(0x4000, 0x7fff) AM_RAMBANK("bank3")
 	AM_RANGE(0x8000, 0x97ff) AM_RAMBANK("bank4") AM_SHARE("mc6847_vram")
 	AM_RANGE(0x9800, 0xbfff) AM_RAMBANK("bank5")
-	AM_RANGE(0xc000, 0xffff) AM_ROM
+	AM_RANGE(0xc000, 0xffff) AM_ROM AM_REGION(Z80_TAG, 0)
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( mc1000_banking_mem, AS_DECRYPTED_OPCODES, 8, mc1000_state )
+	AM_RANGE(0x0000, 0x1fff) AM_RAMBANK("bank1")
+	AM_RANGE(0x2000, 0x27ff) AM_RAMBANK("bank2") AM_SHARE("mc6845_vram")
+	AM_RANGE(0x2800, 0x3fff) AM_RAM AM_SHARE("ram2800")
+	AM_RANGE(0x4000, 0x7fff) AM_RAMBANK("bank3")
+	AM_RANGE(0x8000, 0x97ff) AM_RAMBANK("bank4") AM_SHARE("mc6847_vram")
+	AM_RANGE(0x9800, 0xbfff) AM_RAMBANK("bank5")
+	AM_RANGE(0xc000, 0xffff) AM_READ(rom_banking_r)
 ADDRESS_MAP_END
 
 static ADDRESS_MAP_START( mc1000_io, AS_IO, 8, mc1000_state )
@@ -411,40 +423,45 @@ READ8_MEMBER( mc1000_state::keydata_r )
 	return data;
 }
 
+
+READ8_MEMBER( mc1000_state::rom_banking_r )
+{
+	membank("bank1")->set_entry(0);
+	m_rom0000 = 0;
+	return m_rom->base()[offset];
+}
+
 /* Machine Initialization */
 
 void mc1000_state::machine_start()
 {
-	address_space &program = m_maincpu->space(AS_PROGRAM);
-
 	/* setup memory banking */
-	uint8_t *rom = m_rom->base();
+	m_banked_ram = make_unique_clear<uint8_t[]>(0xc000);
 
-	program.install_readwrite_bank(0x0000, 0x1fff, "bank1");
-	membank("bank1")->configure_entry(0, rom);
-	membank("bank1")->configure_entry(1, rom + 0xc000);
+	membank("bank1")->configure_entry(0, m_banked_ram.get());
+	membank("bank1")->configure_entry(1, m_rom->base());
 	membank("bank1")->set_entry(1);
 
 	m_rom0000 = 1;
 
-	program.install_readwrite_bank(0x2000, 0x27ff, "bank2");
-	membank("bank2")->configure_entry(0, rom + 0x2000);
+	membank("bank2")->configure_entry(0, m_banked_ram.get() + 0x2000);
 	membank("bank2")->configure_entry(1, m_mc6845_video_ram);
 	membank("bank2")->set_entry(0);
 
-	membank("bank3")->configure_entry(0, rom + 0x4000);
+	membank("bank3")->configure_entry(0, m_banked_ram.get() + 0x4000);
 	membank("bank3")->set_entry(0);
 
 	membank("bank4")->configure_entry(0, m_mc6847_video_ram);
-	membank("bank4")->configure_entry(1, rom + 0x8000);
+	membank("bank4")->configure_entry(1, m_banked_ram.get() + 0x8000);
 	membank("bank4")->set_entry(0);
 
-	membank("bank5")->configure_entry(0, rom + 0x9800);
+	membank("bank5")->configure_entry(0, m_banked_ram.get() + 0x9800);
 	membank("bank5")->set_entry(0);
 
 	bankswitch();
 
 	/* register for state saving */
+	save_pointer(NAME(m_banked_ram.get()), 0xc000);
 	save_item(NAME(m_rom0000));
 	save_item(NAME(m_mc6845_bank));
 	save_item(NAME(m_mc6847_bank));
@@ -514,6 +531,7 @@ static MACHINE_CONFIG_START( mc1000, mc1000_state )
 	/* basic machine hardware */
 	MCFG_CPU_ADD(Z80_TAG, Z80, 3579545)
 	MCFG_CPU_PROGRAM_MAP(mc1000_mem)
+	MCFG_CPU_DECRYPTED_OPCODES_MAP(mc1000_banking_mem)
 	MCFG_CPU_IO_MAP(mc1000_io)
 
 	/* timers */
@@ -562,34 +580,13 @@ MACHINE_CONFIG_END
 /* ROMs */
 
 ROM_START( mc1000 )
-	ROM_REGION( 0x10000, Z80_TAG, 0 )
-	ROM_LOAD( "mc1000.ic17", 0xc000, 0x2000, CRC(8e78d80d) SHA1(9480270e67a5db2e7de8bc5c8b9e0bb210d4142b) )
-	ROM_LOAD( "mc1000.ic12", 0xe000, 0x2000, CRC(750c95f0) SHA1(fd766f5ea4481ef7fd4df92cf7d8397cc2b5a6c4) )
+	ROM_REGION( 0x4000, Z80_TAG, 0 )
+	ROM_LOAD( "mc1000.ic17", 0x0000, 0x2000, CRC(8e78d80d) SHA1(9480270e67a5db2e7de8bc5c8b9e0bb210d4142b) )
+	ROM_LOAD( "mc1000.ic12", 0x2000, 0x2000, CRC(750c95f0) SHA1(fd766f5ea4481ef7fd4df92cf7d8397cc2b5a6c4) )
 ROM_END
 
 
-/* Driver Initialization */
-
-DIRECT_UPDATE_MEMBER(mc1000_state::mc1000_direct_update_handler)
-{
-	if (m_rom0000)
-	{
-		if (address >= 0xc000)
-		{
-			membank("bank1")->set_entry(0);
-			m_rom0000 = 0;
-		}
-	}
-
-	return address;
-}
-
-DRIVER_INIT_MEMBER(mc1000_state,mc1000)
-{
-	m_maincpu->space(AS_PROGRAM).set_direct_update_handler(direct_update_delegate(&mc1000_state::mc1000_direct_update_handler, this));
-}
-
 /* System Drivers */
 
 /*    YEAR  NAME        PARENT      COMPAT  MACHINE     INPUT       INIT        COMPANY             FULLNAME        FLAGS */
-COMP( 1985, mc1000,     0,          0,      mc1000,     mc1000, mc1000_state,       mc1000,     "CCE",              "MC-1000",      MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
+COMP( 1985, mc1000,     0,          0,      mc1000,     mc1000, driver_device, 0, "CCE",            "MC-1000",      MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/drivers/mcr.cpp b/src/mame/drivers/mcr.cpp
index 0897918..902e20e 100644
--- a/src/mame/drivers/mcr.cpp
+++ b/src/mame/drivers/mcr.cpp
@@ -207,7 +207,7 @@
     91658 = Lamp Sequencer (DOTron)
     91659 = Flashing Fluorescent Assembly (DOTron)
     91660 = Squawk & Talk (DOTron, NFLFoot)
-    91671 = Chip Squeak Deluxe (SpyHunt)
+    91671 = Cheap Squeak Deluxe (SpyHunt)
     91673 = Lamp Driver (SpyHunt)
     91695 = IPU laserdisk controller (NFLFoot)
     91794 = Optical Encoder Deluxe (DemoDerb)
diff --git a/src/mame/drivers/mcr3.cpp b/src/mame/drivers/mcr3.cpp
index 4f4efe6..9cb022d 100644
--- a/src/mame/drivers/mcr3.cpp
+++ b/src/mame/drivers/mcr3.cpp
@@ -13,9 +13,9 @@
         * Rampage (Sounds Good)
         * Power Drive (Sounds Good)
         * Star Guards (Sounds Good)
-        * Spy Hunter (Chip Squeak Deluxe)
+        * Spy Hunter (Cheap Squeak Deluxe)
         * Crater Raider
-        * Turbo Tag (prototype) (Chip Squeak Deluxe)
+        * Turbo Tag (prototype) (Cheap Squeak Deluxe)
 
     Known bugs:
         * Spy Hunter crashes at the end of the boat level
@@ -107,6 +107,7 @@
 #include "cpu/z80/z80.h"
 #include "machine/z80ctc.h"
 #include "audio/midway.h"
+#include "audio/csd.h"
 #include "machine/nvram.h"
 #include "includes/mcr.h"
 #include "includes/mcr3.h"
@@ -392,7 +393,7 @@ WRITE8_MEMBER(mcr3_state::stargrds_op6_w)
 
 READ8_MEMBER(mcr3_state::spyhunt_ip1_r)
 {
-	return ioport("ssio:IP1")->read() | (m_chip_squeak_deluxe->read(space, 0) << 5);
+	return ioport("ssio:IP1")->read() | (m_cheap_squeak_deluxe->stat_r(space, 0) << 5);
 }
 
 
@@ -436,7 +437,8 @@ WRITE8_MEMBER(mcr3_state::spyhunt_op4_w)
 	m_last_op4 = data;
 
 	/* low 5 bits go to control the Chip Squeak Deluxe */
-	m_chip_squeak_deluxe->write(space, offset, data);
+	m_cheap_squeak_deluxe->sr_w(space, offset, data & 0x0f);
+	m_cheap_squeak_deluxe->sirq_w(BIT(data, 4));
 }
 
 
@@ -1171,11 +1173,11 @@ static MACHINE_CONFIG_DERIVED( mcrscroll, mcrmono )
 MACHINE_CONFIG_END
 
 
-/* Spy Hunter = scrolling system with an SSIO and a chip squeak deluxe */
+/* Spy Hunter = scrolling system with an SSIO and a cheap squeak deluxe */
 static MACHINE_CONFIG_DERIVED( mcrsc_csd, mcrscroll )
 
 	/* basic machine hardware */
-	MCFG_SOUND_ADD("csd", MIDWAY_CHIP_SQUEAK_DELUXE, 0)
+	MCFG_SOUND_ADD("csd", MIDWAY_CHEAP_SQUEAK_DELUXE, 0)
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 1.0)
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 1.0)
 MACHINE_CONFIG_END
@@ -1392,7 +1394,7 @@ ROM_START( spyhunt )
 	ROM_LOAD( "spy-hunter_snd_0_sd_11-18-83.a7",   0x0000, 0x1000, CRC(c95cf31e) SHA1(d1b0e299a27e306ddbc0654fd3a9d981c92afe8c) )
 	ROM_LOAD( "spy-hunter_snd_1_sd_11-18-83.a8",   0x1000, 0x1000, CRC(12aaa48e) SHA1(c6b835fc45e4484a4d52b682ce015caa242c8b4f) )
 
-	ROM_REGION( 0x8000, "csd:cpu", 0 )  /* 32k for the Chip Squeak Deluxe */ // all dated 11-18-83
+	ROM_REGION( 0x8000, "csd:cpu", 0 )  /* 32k for the Cheap Squeak Deluxe */ // all dated 11-18-83
 	ROM_LOAD16_BYTE( "spy-hunter_cs_deluxe_u7_a_11-18-83.u7",   0x00000, 0x2000, CRC(6e689fe7) SHA1(38ad2e9f12b9d389fb2568ebcb32c8bd1ac6879e) )
 	ROM_LOAD16_BYTE( "spy-hunter_cs_deluxe_u17_b_11-18-83.u17", 0x00001, 0x2000, CRC(0d9ddce6) SHA1(d955c0e67fc78b517cc229601ab4023cc5a644c2) )
 	ROM_LOAD16_BYTE( "spy-hunter_cs_deluxe_u8_c_11-18-83.u8",   0x04000, 0x2000, CRC(35563cd0) SHA1(5708d374dd56758194c95118f096ea51bf12bf64) )
@@ -1433,7 +1435,7 @@ ROM_START( spyhuntp )
 	ROM_LOAD( "spy-hunter_snd_0_sd_11-18-83.a7",   0x0000, 0x1000, CRC(c95cf31e) SHA1(d1b0e299a27e306ddbc0654fd3a9d981c92afe8c) )
 	ROM_LOAD( "spy-hunter_snd_1_sd_11-18-83.a8",   0x1000, 0x1000, CRC(12aaa48e) SHA1(c6b835fc45e4484a4d52b682ce015caa242c8b4f) )
 
-	ROM_REGION( 0x8000, "csd:cpu", 0 )  /* 32k for the Chip Squeak Deluxe */
+	ROM_REGION( 0x8000, "csd:cpu", 0 )  /* 32k for the Cheap Squeak Deluxe */
 	ROM_LOAD16_BYTE( "spy-hunter_cs_deluxe_u7_a_11-18-83.u7",   0x00000, 0x2000, CRC(6e689fe7) SHA1(38ad2e9f12b9d389fb2568ebcb32c8bd1ac6879e) )
 	ROM_LOAD16_BYTE( "spy-hunter_cs_deluxe_u17_b_11-18-83.u17", 0x00001, 0x2000, CRC(0d9ddce6) SHA1(d955c0e67fc78b517cc229601ab4023cc5a644c2) )
 	ROM_LOAD16_BYTE( "spy-hunter_cs_deluxe_u8_c_11-18-83.u8",   0x04000, 0x2000, CRC(35563cd0) SHA1(5708d374dd56758194c95118f096ea51bf12bf64) )
@@ -1509,7 +1511,7 @@ ROM_START( turbotag )
 
 	ROM_REGION( 0x10000, "ssio:cpu", ROMREGION_ERASE00 )
 
-	ROM_REGION( 0x8000, "csd:cpu", 0 )  /* 32k for the Chip Squeak Deluxe */
+	ROM_REGION( 0x8000, "csd:cpu", 0 )  /* 32k for the Cheap Squeak Deluxe */
 	ROM_LOAD16_BYTE( "ttu7.bin",  0x00000, 0x2000, CRC(8ebb3302) SHA1(c516abdae6eea524a6d2a039ed9bd7dff72ab986) )
 	ROM_LOAD16_BYTE( "ttu17.bin", 0x00001, 0x2000, CRC(605d6c74) SHA1(a6c2bc95cca372fa823ab256c9dd1f92b6ba45fd) )
 	ROM_LOAD16_BYTE( "ttu8.bin",  0x04000, 0x2000, CRC(6bfcb22a) SHA1(7b895e3ae1e99f195bb32b052f801b58c63a401c) )
diff --git a/src/mame/drivers/mcr68.cpp b/src/mame/drivers/mcr68.cpp
index f81a032..ff5df1a 100644
--- a/src/mame/drivers/mcr68.cpp
+++ b/src/mame/drivers/mcr68.cpp
@@ -7,7 +7,6 @@
     driver by Bryan McPhail, Aaron Giles
 
     Games supported:
-        * Zwackery (Chip Squeak Deluxe)
         * Xenopohobe (Sounds Good)
         * Spy Hunter II (Sounds Good/Turbo Chip Squeak)
         * Blasted (Sounds Good)
@@ -64,37 +63,6 @@
 
 /*************************************
  *
- *  Zwackery-specific handlers
- *
- *************************************/
-
-READ8_MEMBER(mcr68_state::zwackery_port_2_r)
-{
-	int result = ioport("IN2")->read();
-	int wheel = ioport("IN5")->read();
-
-	return result | ((wheel >> 2) & 0x3e);
-}
-
-
-READ16_MEMBER(mcr68_state::zwackery_6840_r)
-{
-	/* Zwackery does a timer test:                          */
-	/* It loads $1388 into one of the timers clocked by E   */
-	/* Then it sits in a tight loop counting down from $4E4 */
-	/*       BTST #$1,($2,A0)                               */
-	/*       DBNE D1,*-6                                    */
-	/* It expects D1 to end up between 0 and 5; in order to */
-	/* make this happen, we must assume that reads from the */
-	/* 6840 take 14 additional cycles                       */
-	space.device().execute().adjust_icount(-14);
-	return mcr68_6840_upper_r(space,offset,0xffff);
-}
-
-
-
-/*************************************
- *
  *  Xenophobe-specific handlers
  *
  *************************************/
@@ -308,7 +276,7 @@ static ADDRESS_MAP_START( mcr68_map, AS_PROGRAM, 16, mcr68_state )
 	AM_RANGE(0x071000, 0x071fff) AM_RAM
 	AM_RANGE(0x080000, 0x080fff) AM_RAM AM_SHARE("spriteram")
 	AM_RANGE(0x090000, 0x09007f) AM_DEVWRITE("palette", palette_device, write) AM_SHARE("palette")
-	AM_RANGE(0x0a0000, 0x0a000f) AM_READWRITE(mcr68_6840_upper_r, mcr68_6840_upper_w)
+	AM_RANGE(0x0a0000, 0x0a000f) AM_DEVREADWRITE8("ptm", ptm6840_device, read, write, 0xff00)
 	AM_RANGE(0x0b0000, 0x0bffff) AM_DEVWRITE("watchdog", watchdog_timer_device, reset16_w)
 	AM_RANGE(0x0d0000, 0x0dffff) AM_READ_PORT("IN0")
 	AM_RANGE(0x0e0000, 0x0effff) AM_READ_PORT("IN1")
@@ -319,28 +287,6 @@ ADDRESS_MAP_END
 
 /*************************************
  *
- *  Zwackery main CPU memory handlers
- *
- *************************************/
-
-static ADDRESS_MAP_START( zwackery_map, AS_PROGRAM, 16, mcr68_state )
-	ADDRESS_MAP_UNMAP_HIGH
-	AM_RANGE(0x000000, 0x037fff) AM_ROM
-	AM_RANGE(0x080000, 0x080fff) AM_RAM
-	AM_RANGE(0x084000, 0x084fff) AM_RAM
-	AM_RANGE(0x100000, 0x10000f) AM_READ(zwackery_6840_r) AM_WRITE(mcr68_6840_upper_w)
-	AM_RANGE(0x104000, 0x104007) AM_DEVREADWRITE8("pia0", pia6821_device, read, write, 0xff00)
-	AM_RANGE(0x108000, 0x108007) AM_DEVREADWRITE8("pia1", pia6821_device, read, write, 0x00ff)
-	AM_RANGE(0x10c000, 0x10c007) AM_DEVREADWRITE8("pia2", pia6821_device, read, write, 0x00ff)
-	AM_RANGE(0x800000, 0x800fff) AM_RAM_WRITE(zwackery_videoram_w) AM_SHARE("videoram")
-	AM_RANGE(0x802000, 0x803fff) AM_RAM_DEVWRITE("palette", palette_device, write) AM_SHARE("palette")
-	AM_RANGE(0xc00000, 0xc00fff) AM_RAM_WRITE(zwackery_spriteram_w) AM_SHARE("spriteram")
-ADDRESS_MAP_END
-
-
-
-/*************************************
- *
  *  Pigskin CPU memory handlers
  *
  *************************************/
@@ -357,7 +303,7 @@ static ADDRESS_MAP_START( pigskin_map, AS_PROGRAM, 16, mcr68_state )
 	AM_RANGE(0x120000, 0x120001) AM_READWRITE(pigskin_protection_r, pigskin_protection_w)
 	AM_RANGE(0x140000, 0x143fff) AM_RAM
 	AM_RANGE(0x160000, 0x1607ff) AM_RAM AM_SHARE("spriteram")
-	AM_RANGE(0x180000, 0x18000f) AM_READWRITE(mcr68_6840_upper_r, mcr68_6840_upper_w)
+	AM_RANGE(0x180000, 0x18000f) AM_DEVREADWRITE8("ptm", ptm6840_device, read, write, 0xff00)
 	AM_RANGE(0x1a0000, 0x1affff) AM_WRITE(archrivl_control_w)
 	AM_RANGE(0x1e0000, 0x1effff) AM_READ_PORT("IN0")
 ADDRESS_MAP_END
@@ -380,7 +326,7 @@ static ADDRESS_MAP_START( trisport_map, AS_PROGRAM, 16, mcr68_state )
 	AM_RANGE(0x120000, 0x12007f) AM_DEVWRITE("palette", palette_device, write) AM_SHARE("palette")
 	AM_RANGE(0x140000, 0x1407ff) AM_RAM AM_SHARE("spriteram")
 	AM_RANGE(0x160000, 0x160fff) AM_RAM_WRITE(mcr68_videoram_w) AM_SHARE("videoram")
-	AM_RANGE(0x180000, 0x18000f) AM_READWRITE(mcr68_6840_upper_r, mcr68_6840_upper_w)
+	AM_RANGE(0x180000, 0x18000f) AM_DEVREADWRITE8("ptm", ptm6840_device, read, write, 0xff00)
 	AM_RANGE(0x1a0000, 0x1affff) AM_WRITE(archrivl_control_w)
 	AM_RANGE(0x1c0000, 0x1cffff) AM_DEVWRITE("watchdog", watchdog_timer_device, reset16_w)
 	AM_RANGE(0x1e0000, 0x1effff) AM_READ_PORT("IN0")
@@ -394,62 +340,6 @@ ADDRESS_MAP_END
  *
  *************************************/
 
-static INPUT_PORTS_START( zwackery )
-	PORT_START("IN0")
-	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START1 )
-	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START2 )
-	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_COIN1 )
-	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_COIN2 )
-	PORT_SERVICE( 0x0010, IP_ACTIVE_LOW )
-	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_SERVICE1 )
-	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_TILT )
-	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 )    /* sword */
-
-	PORT_START("IN1")
-	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY
-	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY
-	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY
-	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY
-	PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_SPECIAL )    /* sound communications */
-
-	PORT_START("IN2")
-	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON3 )    /* spell up */
-	PORT_BIT( 0x3e, IP_ACTIVE_HIGH, IPT_UNUSED )    /* encoder wheel */
-	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON2 )    /* shield */
-	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON4 )    /* spell down */
-
-	PORT_START("IN3")
-	PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
-
-	PORT_START("DSW")
-	PORT_DIPNAME( 0x07, 0x00, DEF_STR( Coinage ) )      PORT_DIPLOCATION("SW1:1,2,3")
-	PORT_DIPSETTING(    0x05, DEF_STR( 6C_1C ) )
-	PORT_DIPSETTING(    0x04, DEF_STR( 5C_1C ) )
-	PORT_DIPSETTING(    0x03, DEF_STR( 4C_1C ) )
-	PORT_DIPSETTING(    0x02, DEF_STR( 3C_1C ) )
-	PORT_DIPSETTING(    0x01, DEF_STR( 2C_1C ) )
-	PORT_DIPSETTING(    0x00, DEF_STR( 1C_1C ) )
-	PORT_DIPSETTING(    0x06, DEF_STR( 1C_2C ) )
-	PORT_DIPSETTING(    0x07, DEF_STR( Free_Play ) )
-	PORT_DIPNAME( 0x38, 0x00, "Buy-in" )            PORT_DIPLOCATION("SW1:4,5,6")
-	PORT_DIPSETTING(    0x00, "1 coin" )
-	PORT_DIPSETTING(    0x08, "2 coins" )
-	PORT_DIPSETTING(    0x10, "3 coins" )
-	PORT_DIPSETTING(    0x18, "4 coins" )
-	PORT_DIPSETTING(    0x20, "5 coins" )
-	PORT_DIPSETTING(    0x28, "6 coins" )
-	PORT_DIPSETTING(    0x30, "7 coins" )
-	PORT_DIPSETTING(    0x38, DEF_STR( None ) )
-	PORT_DIPNAME( 0xc0, 0x00, DEF_STR( Difficulty ) )   PORT_DIPLOCATION("SW1:7,8")
-	PORT_DIPSETTING(    0xc0, DEF_STR( Easier ) )
-	PORT_DIPSETTING(    0x00, DEF_STR( Normal ) )
-	PORT_DIPSETTING(    0x40, DEF_STR( Harder ) )
-	PORT_DIPSETTING(    0x80, DEF_STR( Hardest ) )
-
-	PORT_START("IN5")
-	PORT_BIT( 0xff, 0x00, IPT_DIAL ) PORT_SENSITIVITY(50) PORT_KEYDELTA(10) PORT_CODE_DEC(KEYCODE_Z) PORT_CODE_INC(KEYCODE_X) PORT_REVERSE
-INPUT_PORTS_END
-
 
 static INPUT_PORTS_START( xenophob )
 	PORT_START("IN0")
@@ -956,29 +846,11 @@ static const gfx_layout mcr68_sprite_layout =
 	32*32
 };
 
-static const gfx_layout zwackery_layout =
-{
-	16,16,
-	RGN_FRAC(1,2),
-	8,
-	{ 0, 0, 0, 0, 0, 0, 0, 0 },
-	{ STEP4(3,-1), STEP4(11,-1), STEP4(19,-1), STEP4(27,-1) },
-	{ 4, RGN_FRAC(1,2)+4, 0, RGN_FRAC(1,2)+0, 36, RGN_FRAC(1,2)+36, 32, RGN_FRAC(1,2)+32,
-		68, RGN_FRAC(1,2)+68, 64, RGN_FRAC(1,2)+64, 100, RGN_FRAC(1,2)+100, 96, RGN_FRAC(1,2)+96 },
-	128
-};
-
 static GFXDECODE_START( mcr68 )
 	GFXDECODE_SCALE( "gfx1", 0, mcr68_bg_layout,     0, 4, 2, 2 )
 	GFXDECODE_ENTRY( "gfx2", 0, mcr68_sprite_layout, 0, 4 )
 GFXDECODE_END
 
-static GFXDECODE_START( zwackery )
-	GFXDECODE_ENTRY( "gfx1", 0, zwackery_layout,       0, 16 )
-	GFXDECODE_ENTRY( "gfx2", 0, mcr68_sprite_layout, 0x800, 32 )
-	GFXDECODE_ENTRY( "gfx1", 0, zwackery_layout,       0, 16 )  /* yes, an extra copy */
-GFXDECODE_END
-
 
 
 /*************************************
@@ -1002,7 +874,6 @@ GFXDECODE_END
 
     Ideal CPU timings, based on counter usage:
 
-        Zwackery:     7652400
         Xenophobe:    7723800
         Spy Hunter II:7723800
         Blasted:      7798800
@@ -1015,68 +886,20 @@ GFXDECODE_END
 
 =================================================================*/
 
-static MACHINE_CONFIG_START( zwackery, mcr68_state )
-
-	/* basic machine hardware */
-	MCFG_CPU_ADD("maincpu", M68000, 7652400)    /* should be XTAL_16MHz/2 */
-	MCFG_CPU_PROGRAM_MAP(zwackery_map)
-	MCFG_CPU_VBLANK_INT_DRIVER("screen", mcr68_state,  mcr68_interrupt)
-
-		MCFG_WATCHDOG_ADD("watchdog")
-//  MCFG_WATCHDOG_VBLANK_INIT("screen", 8)
-	MCFG_MACHINE_START_OVERRIDE(mcr68_state,zwackery)
-	MCFG_MACHINE_RESET_OVERRIDE(mcr68_state,zwackery)
-
-	MCFG_DEVICE_ADD("pia0", PIA6821, 0)
-	MCFG_PIA_READPB_HANDLER(IOPORT("IN0"))
-	MCFG_PIA_WRITEPA_HANDLER(WRITE8(mcr68_state, zwackery_pia0_w))
-	MCFG_PIA_IRQA_HANDLER(WRITELINE(mcr68_state, zwackery_pia_irq))
-	MCFG_PIA_IRQB_HANDLER(WRITELINE(mcr68_state, zwackery_pia_irq))
-
-	MCFG_DEVICE_ADD("pia1", PIA6821, 0)
-	MCFG_PIA_READPA_HANDLER(READ8(mcr68_state,zwackery_port_1_r))
-	MCFG_PIA_READPB_HANDLER(READ8(mcr68_state, zwackery_port_2_r))
-	MCFG_PIA_WRITEPA_HANDLER(WRITE8(mcr68_state, zwackery_pia1_w))
-	MCFG_PIA_CA2_HANDLER(WRITELINE(mcr68_state, zwackery_ca2_w))
-
-	MCFG_DEVICE_ADD("pia2", PIA6821, 0)
-	MCFG_PIA_READPA_HANDLER(READ8(mcr68_state, zwackery_port_3_r))
-	MCFG_PIA_READPB_HANDLER(IOPORT("DSW"))
-
-	/* video hardware */
-	MCFG_SCREEN_ADD("screen", RASTER)
-	MCFG_SCREEN_REFRESH_RATE(30)
-	MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500) /* not accurate */)
-	MCFG_SCREEN_SIZE(32*16, 30*16)
-	MCFG_SCREEN_VISIBLE_AREA(0, 32*16-1, 0, 30*16-1)
-	MCFG_SCREEN_UPDATE_DRIVER(mcr68_state, screen_update_zwackery)
-	MCFG_SCREEN_PALETTE("palette")
-
-	MCFG_GFXDECODE_ADD("gfxdecode", "palette", zwackery)
-	MCFG_PALETTE_ADD("palette", 4096)
-	MCFG_PALETTE_FORMAT(xRRRRRBBBBBGGGGG_inverted)
-
-	MCFG_VIDEO_START_OVERRIDE(mcr68_state,zwackery)
-
-	/* sound hardware */
-	MCFG_SPEAKER_STANDARD_MONO("speaker")
-	MCFG_SOUND_ADD("csd", MIDWAY_CHIP_SQUEAK_DELUXE, 0)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "speaker", 1.0)
-MACHINE_CONFIG_END
-
-
 static MACHINE_CONFIG_START( mcr68, mcr68_state )
 
 	/* basic machine hardware */
 	MCFG_CPU_ADD("maincpu", M68000, 7723800)
 	MCFG_CPU_PROGRAM_MAP(mcr68_map)
-	MCFG_CPU_VBLANK_INT_DRIVER("screen", mcr68_state,  mcr68_interrupt)
 
 	MCFG_WATCHDOG_ADD("watchdog")
 	MCFG_WATCHDOG_VBLANK_INIT("screen", 8)
 	MCFG_MACHINE_START_OVERRIDE(mcr68_state,mcr68)
 	MCFG_MACHINE_RESET_OVERRIDE(mcr68_state,mcr68)
 
+	MCFG_DEVICE_ADD("ptm", PTM6840, 7723800 / 10)
+	MCFG_PTM6840_IRQ_CB(INPUTLINE("maincpu", 2))
+
 	/* video hardware */
 	MCFG_SCREEN_ADD("screen", RASTER)
 	MCFG_SCREEN_REFRESH_RATE(30)
@@ -1086,6 +909,8 @@ static MACHINE_CONFIG_START( mcr68, mcr68_state )
 	MCFG_SCREEN_UPDATE_DRIVER(mcr68_state, screen_update_mcr68)
 	MCFG_SCREEN_PALETTE("palette")
 
+	MCFG_TIMER_DRIVER_ADD_SCANLINE("scantimer", mcr68_state, scanline_cb, "screen", 0, 1)
+
 	MCFG_GFXDECODE_ADD("gfxdecode", "palette", mcr68)
 	MCFG_PALETTE_ADD("palette", 64)
 	MCFG_PALETTE_FORMAT(xxxxxxxRRRBBBGGG)
@@ -1164,67 +989,6 @@ MACHINE_CONFIG_END
  *
  *************************************/
 
-ROM_START( zwackery )
-	ROM_REGION( 0x40000, "maincpu", 0 )
-	ROM_LOAD16_BYTE( "pro0.bin",   0x00000, 0x4000, CRC(6fb9731c) SHA1(ee5b297ef2b4cf20df5e776f1c585b51f174bfa7) )
-	ROM_LOAD16_BYTE( "pro1.bin",   0x00001, 0x4000, CRC(84b92555) SHA1(9b4af81374828c1742c1e13fc425eea2973b0867) )
-	ROM_LOAD16_BYTE( "pro2.bin",   0x08000, 0x4000, CRC(e6977a2a) SHA1(602bf3f7e0f4080cb5b72d8fd3ee9fd11f27c558) )
-	ROM_LOAD16_BYTE( "pro3.bin",   0x08001, 0x4000, CRC(f5d0a60e) SHA1(7e0e4936cb37ac16d6db5533ae4aecdfb07ead93) )
-	ROM_LOAD16_BYTE( "pro4.bin",   0x10000, 0x4000, CRC(ec5841d9) SHA1(4bafe614e8993994b0ea9aedc8dc2474361e4594) )
-	ROM_LOAD16_BYTE( "pro5.bin",   0x10001, 0x4000, CRC(d7d99ce0) SHA1(fdf428ab9c96dae555d49bac47495613ba265452) )
-	ROM_LOAD16_BYTE( "pro6.bin",   0x18000, 0x4000, CRC(b9fe7bf5) SHA1(a94f80f49b4520a2c1098eee8983560b4ecdf3d5) )
-	ROM_LOAD16_BYTE( "pro7.bin",   0x18001, 0x4000, CRC(5e261b3b) SHA1(dcf99f528c9e3b4f8b52d413c088559bfb37d733) )
-	ROM_LOAD16_BYTE( "pro8.bin",   0x20000, 0x4000, CRC(55e380a5) SHA1(e3fef8486858cd714086449327a93b4a70ae73ff) )
-	ROM_LOAD16_BYTE( "pro9.bin",   0x20001, 0x4000, CRC(12249dca) SHA1(154170286047ea78645d45dfdd895a597dad17da) )
-	ROM_LOAD16_BYTE( "pro10.bin",  0x28000, 0x4000, CRC(6a39a8ca) SHA1(8ac9c3e60dc6f1918bfb95acf3ee170cedfb20ea) )
-	ROM_LOAD16_BYTE( "pro11.bin",  0x28001, 0x4000, CRC(ad6b45bc) SHA1(118496e898654b028f008a3d493e693ba000ef38) )
-	ROM_LOAD16_BYTE( "pro12.bin",  0x30000, 0x4000, CRC(e2d25e1f) SHA1(5d8ff303441eccf431422b453a173983a4513630) )
-	ROM_LOAD16_BYTE( "pro13.bin",  0x30001, 0x4000, CRC(e131f9b8) SHA1(08b131f2acc84d4c2c931bfd24e7de3d92a8a817) )
-
-	ROM_REGION( 0x20000, "csd:cpu", 0 )
-	ROM_LOAD16_BYTE( "csd7.bin",  0x00000, 0x2000, CRC(5501f54b) SHA1(84c0851fb868e81400cfe3ebfd7b91fe98a47bac) )
-	ROM_LOAD16_BYTE( "csd17.bin", 0x00001, 0x2000, CRC(2e482580) SHA1(92bd3e64ff580800ee16579d97bcb8b3bd9f755c) )
-	ROM_LOAD16_BYTE( "csd8.bin",  0x04000, 0x2000, CRC(13366575) SHA1(bcf25a7d4c6b2ccd7cd9978edafc66ef0cadfe72) )
-	ROM_LOAD16_BYTE( "csd18.bin", 0x04001, 0x2000, CRC(bcfe5820) SHA1(ca32daa645851a2373b3cdb8a5e63ebda84aa762) )
-
-	ROM_REGION( 0x8000, "gfx1", ROMREGION_INVERT )
-	ROM_LOAD( "tileh.bin",    0x00000, 0x4000, CRC(a7237eb1) SHA1(197e5838ac2bc732ae9eb33a9257b9391d50abf8) )
-	ROM_LOAD( "tileg.bin",    0x04000, 0x4000, CRC(626cc69b) SHA1(86142bafa78f45d1a0bed0b83f3558b21384fa1a) )
-
-	ROM_REGION( 0x20000, "gfx2", 0 )
-	ROM_LOAD( "spr6h.bin",    0x00000, 0x4000, CRC(a51158dc) SHA1(8d3b0054950443fdf57f83dcb973d05f6c7ad9c8) )
-	ROM_LOAD( "spr7h.bin",    0x04000, 0x4000, CRC(941feecf) SHA1(8e88c956332e78dc7e55139879f2272116415714) )
-	ROM_LOAD( "spr6j.bin",    0x08000, 0x4000, CRC(f3eef316) SHA1(026e18bdfdda8cc9d0774e6d9d758686bf16992c) )
-	ROM_LOAD( "spr7j.bin",    0x0c000, 0x4000, CRC(a8a34033) SHA1(abd9fde84bb079c84126ad04d584ec03b44b60cd) )
-	ROM_LOAD( "spr10h.bin",   0x10000, 0x4000, CRC(a99daea6) SHA1(c323e05f398b7e9e04b75fd8ac5e8ab675236d66) )
-	ROM_LOAD( "spr11h.bin",   0x14000, 0x4000, CRC(c1a767fb) SHA1(c16e09b39b09d409b534ce4c53366e43237a3759) )
-	ROM_LOAD( "spr10j.bin",   0x18000, 0x4000, CRC(4dd04376) SHA1(069b64397e7a961c1fc246671472f759bd9f6c03) )
-	ROM_LOAD( "spr11j.bin",   0x1c000, 0x4000, CRC(e8c6a880) SHA1(dd3d52ddbc36e244b96cfb87e6a80adb94626407) )
-
-	ROM_REGION( 0x8000, "gfx3", 0 ) /* bg color maps */
-	ROM_LOAD16_BYTE( "tilef.bin",  0x0000, 0x4000, CRC(a0dfcd7e) SHA1(0fc6723eddef2a96de9bf1f48006dd067c148540) )
-	ROM_LOAD16_BYTE( "tilee.bin",  0x0001, 0x4000, CRC(ab504dc8) SHA1(4ebdcd42624e94c29ccdb8247bfff2d8e936ddd7) )
-
-	ROM_REGION( 0x000D, "plds", 0 )
-	/* According to the manual these pal's are located on the "Venus CPU" board */
-	ROM_LOAD( "pal.d5",    0x0000, 0x00001, NO_DUMP ) /* marked H-T in manual */
-	ROM_LOAD( "pal.d2",    0x0001, 0x00001, NO_DUMP ) /* marked V-T in manual */
-	ROM_LOAD( "pal.d4",    0x0002, 0x00001, NO_DUMP ) /* marked MISC V&H PAL in manual */
-	ROM_LOAD( "pal.d3",    0x0003, 0x00001, NO_DUMP ) /* marked MISC CUSTOM PAL in manual */
-	ROM_LOAD( "pal.e6",    0x0004, 0x00001, NO_DUMP ) /* marked CPU WTS PAL in manual*/
-	ROM_LOAD( "pal.f8",    0x0005, 0x00001, NO_DUMP ) /* marked CPU IOC PAL in manual*/
-	ROM_LOAD( "pal.a5",    0x0006, 0x00001, NO_DUMP ) /* marked CPU RMD PAL in manual*/
-	/* According to the manual these pal's are located on the "Venus VIDEO" board */
-	ROM_LOAD( "pal.1f",    0x0007, 0x00001, NO_DUMP ) /* marked PAL FGBDCD in manual*/
-	ROM_LOAD( "pal.1d",    0x0008, 0x00001, NO_DUMP ) /* marked PAL HCT in manual*/
-	/* According to the manual these pal's are located on the "Venus BACKGROUND" board */
-	ROM_LOAD( "pal.1c",    0x0009, 0x00001, NO_DUMP ) /* marked BGBPE PAL in manual*/
-	ROM_LOAD( "pal.5c",    0x000a, 0x00001, NO_DUMP ) /* marked HCT PAL in manual*/
-	ROM_LOAD( "pal.5j",    0x000b, 0x00001, NO_DUMP ) /* marked BGBDCD PAL in manual*/
-	/* According to the manual this pal is located on the "Artificial Artist" board */
-	ROM_LOAD( "pal20.u15", 0x000c, 0x00001, NO_DUMP ) /* marked CSD002R0 in manual, pal type not specified */
-ROM_END
-
 /*
     Xenophobe
 
@@ -1700,15 +1464,6 @@ void mcr68_state::mcr68_common_init(int clip, int xoffset)
 }
 
 
-DRIVER_INIT_MEMBER(mcr68_state,zwackery)
-{
-	mcr68_common_init(0, 0);
-
-	/* Zwackery doesn't care too much about this value; currently taken from Blasted */
-	m_timing_factor = attotime::from_hz(m_maincpu->unscaled_clock() / 10) * (256 + 16);
-}
-
-
 DRIVER_INIT_MEMBER(mcr68_state,xenophob)
 {
 	mcr68_common_init(0, -4);
@@ -1748,7 +1503,7 @@ DRIVER_INIT_MEMBER(mcr68_state,blasted)
 	m_maincpu->space(AS_PROGRAM).install_write_handler(0x0c0000, 0x0cffff, write16_delegate(FUNC(mcr68_state::blasted_control_w),this));
 
 	/* 6840 is mapped to the lower 8 bits */
-	m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x0a0000, 0x0a000f, read16_delegate(FUNC(mcr68_state::mcr68_6840_lower_r),this), write16_delegate(FUNC(mcr68_state::mcr68_6840_lower_w),this));
+	m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x0a0000, 0x0a000f, read8_delegate(FUNC(ptm6840_device::read), &(*m_ptm)), write8_delegate(FUNC(ptm6840_device::write), &(*m_ptm)), 0x00ff);
 }
 
 DRIVER_INIT_MEMBER(mcr68_state,intlaser)
@@ -1779,7 +1534,7 @@ DRIVER_INIT_MEMBER(mcr68_state,archrivl)
 	m_maincpu->space(AS_PROGRAM).install_read_handler(0x0e0000, 0x0effff, read16_delegate(FUNC(mcr68_state::archrivl_port_1_r),this));
 
 	/* 6840 is mapped to the lower 8 bits */
-	m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x0a0000, 0x0a000f, read16_delegate(FUNC(mcr68_state::mcr68_6840_lower_r),this), write16_delegate(FUNC(mcr68_state::mcr68_6840_lower_w),this));
+	m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x0a0000, 0x0a000f, read8_delegate(FUNC(ptm6840_device::read), &(*m_ptm)), write8_delegate(FUNC(ptm6840_device::write), &(*m_ptm)), 0x00ff);
 }
 
 READ16_MEMBER(mcr68_state::archrivlb_port_1_r)
@@ -1801,7 +1556,7 @@ DRIVER_INIT_MEMBER(mcr68_state,archrivlb)
 	m_maincpu->space(AS_PROGRAM).install_read_handler(0x0e0000, 0x0effff, read16_delegate(FUNC(mcr68_state::archrivlb_port_1_r),this));
 
 	/* 6840 is mapped to the lower 8 bits */
-	m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x0a0000, 0x0a000f, read16_delegate(FUNC(mcr68_state::mcr68_6840_lower_r),this), write16_delegate(FUNC(mcr68_state::mcr68_6840_lower_w),this));
+	m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x0a0000, 0x0a000f, read8_delegate(FUNC(ptm6840_device::read), &(*m_ptm)), write8_delegate(FUNC(ptm6840_device::write), &(*m_ptm)), 0x00ff);
 }
 
 
@@ -1835,8 +1590,6 @@ DRIVER_INIT_MEMBER(mcr68_state,trisport)
  *
  *************************************/
 
-GAME( 1984, zwackery, 0,        zwackery, zwackery, mcr68_state, zwackery, ROT0,   "Bally Midway", "Zwackery", MACHINE_SUPPORTS_SAVE )
-
 GAME( 1987, xenophob, 0,        xenophob, xenophob, mcr68_state, xenophob, ROT0,   "Bally Midway", "Xenophobe", MACHINE_SUPPORTS_SAVE )
 
 GAME( 1987, spyhunt2, 0,        spyhunt2, spyhunt2, mcr68_state, spyhunt2, ROT0,   "Bally Midway", "Spy Hunter II (rev 2)", MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/drivers/meijinsn.cpp b/src/mame/drivers/meijinsn.cpp
index ed85ddf..f3c38c0 100644
--- a/src/mame/drivers/meijinsn.cpp
+++ b/src/mame/drivers/meijinsn.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /*
  Meijinsen (snk/alpha)
diff --git a/src/mame/drivers/metro.cpp b/src/mame/drivers/metro.cpp
index 4822ff1..94f2b29 100644
--- a/src/mame/drivers/metro.cpp
+++ b/src/mame/drivers/metro.cpp
@@ -3646,13 +3646,12 @@ static MACHINE_CONFIG_START( msgogo, metro_state )
 	MCFG_PALETTE_FORMAT(GGGGGRRRRRBBBBBx)
 
 	/* sound hardware */
-	MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
+	MCFG_SPEAKER_STANDARD_MONO("mono")
 
 	MCFG_SOUND_ADD("ymf", YMF278B, YMF278B_STD_CLOCK)
 	MCFG_DEVICE_ADDRESS_MAP(AS_0, ymf278_map)
 	MCFG_YMF278B_IRQ_HANDLER(INPUTLINE("maincpu", 2))
-	MCFG_SOUND_ROUTE(0, "lspeaker", 1.0)
-	MCFG_SOUND_ROUTE(1, "rspeaker", 1.0)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
 MACHINE_CONFIG_END
 
 static MACHINE_CONFIG_DERIVED( balcube, msgogo )
@@ -3712,18 +3711,16 @@ static MACHINE_CONFIG_START( daitorid, metro_state )
 	MCFG_PALETTE_FORMAT(GGGGGRRRRRBBBBBx)
 
 	/* sound hardware */
-	MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
+	MCFG_SPEAKER_STANDARD_MONO("mono")
 
 	MCFG_GENERIC_LATCH_8_ADD("soundlatch")
 
 	MCFG_YM2151_ADD("ymsnd", XTAL_3_579545MHz)
 	MCFG_YM2151_IRQ_HANDLER(INPUTLINE("audiocpu", UPD7810_INTF2))
-	MCFG_SOUND_ROUTE(0, "lspeaker", 0.80)
-	MCFG_SOUND_ROUTE(1, "rspeaker", 0.80)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.80)
 
 	MCFG_OKIM6295_ADD("oki", 1200000, OKIM6295_PIN7_HIGH) // sample rate =  M6295 clock / 132
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.40)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.40)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.40)
 MACHINE_CONFIG_END
 
 
@@ -3755,17 +3752,15 @@ static MACHINE_CONFIG_START( dharma, metro_state )
 	MCFG_PALETTE_FORMAT(GGGGGRRRRRBBBBBx)
 
 	/* sound hardware */
-	MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
+	MCFG_SPEAKER_STANDARD_MONO("mono")
 
 	MCFG_GENERIC_LATCH_8_ADD("soundlatch")
 
 	MCFG_OKIM6295_ADD("oki", XTAL_24MHz/20, OKIM6295_PIN7_HIGH) // sample rate =  M6295 clock / 132
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.10)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.10)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.10)
 
 	MCFG_SOUND_ADD("ymsnd", YM2413, XTAL_3_579545MHz)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.90)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.90)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.90)
 MACHINE_CONFIG_END
 
 
@@ -3797,17 +3792,15 @@ static MACHINE_CONFIG_START( karatour, metro_state )
 	MCFG_PALETTE_FORMAT(GGGGGRRRRRBBBBBx)
 
 	/* sound hardware */
-	MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
+	MCFG_SPEAKER_STANDARD_MONO("mono")
 
 	MCFG_GENERIC_LATCH_8_ADD("soundlatch")
 
 	MCFG_OKIM6295_ADD("oki", XTAL_24MHz/20, OKIM6295_PIN7_HIGH) // was /128.. so pin 7 not verified
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.10)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.10)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.10)
 
 	MCFG_SOUND_ADD("ymsnd", YM2413, XTAL_3_579545MHz)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.90)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.90)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.90)
 MACHINE_CONFIG_END
 
 
@@ -3839,17 +3832,15 @@ static MACHINE_CONFIG_START( 3kokushi, metro_state )
 	MCFG_PALETTE_FORMAT(GGGGGRRRRRBBBBBx)
 
 	/* sound hardware */
-	MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
+	MCFG_SPEAKER_STANDARD_MONO("mono")
 
 	MCFG_GENERIC_LATCH_8_ADD("soundlatch")
 
 	MCFG_OKIM6295_ADD("oki", XTAL_24MHz/20, OKIM6295_PIN7_HIGH) // was /128.. so pin 7 not verified
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.10)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.10)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.10)
 
 	MCFG_SOUND_ADD("ymsnd", YM2413, XTAL_3_579545MHz)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.90)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.90)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.90)
 MACHINE_CONFIG_END
 
 
@@ -3881,17 +3872,15 @@ static MACHINE_CONFIG_START( lastfort, metro_state )
 	MCFG_PALETTE_FORMAT(GGGGGRRRRRBBBBBx)
 
 	/* sound hardware */
-	MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
+	MCFG_SPEAKER_STANDARD_MONO("mono")
 
 	MCFG_GENERIC_LATCH_8_ADD("soundlatch")
 
 	MCFG_OKIM6295_ADD("oki", XTAL_24MHz/20, OKIM6295_PIN7_LOW) // sample rate =  M6295 clock / 165
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.10)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.10)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.10)
 
 	MCFG_SOUND_ADD("ymsnd", YM2413, XTAL_3_579545MHz)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.90)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.90)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.90)
 MACHINE_CONFIG_END
 
 static MACHINE_CONFIG_START( lastforg, metro_state )
@@ -3922,17 +3911,15 @@ static MACHINE_CONFIG_START( lastforg, metro_state )
 	MCFG_PALETTE_FORMAT(GGGGGRRRRRBBBBBx)
 
 	/* sound hardware */
-	MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
+	MCFG_SPEAKER_STANDARD_MONO("mono")
 
 	MCFG_GENERIC_LATCH_8_ADD("soundlatch")
 
 	MCFG_OKIM6295_ADD("oki", XTAL_24MHz/20, OKIM6295_PIN7_HIGH) // was /128.. so pin 7 not verified
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.10)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.10)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.10)
 
 	MCFG_SOUND_ADD("ymsnd", YM2413, XTAL_3_579545MHz)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.90)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.90)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.90)
 MACHINE_CONFIG_END
 
 static MACHINE_CONFIG_START( dokyusei, metro_state )
@@ -3958,15 +3945,13 @@ static MACHINE_CONFIG_START( dokyusei, metro_state )
 	MCFG_PALETTE_FORMAT(GGGGGRRRRRBBBBBx)
 
 	/* sound hardware */
-	MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
+	MCFG_SPEAKER_STANDARD_MONO("mono")
 
 	MCFG_OKIM6295_ADD("oki", 1056000, OKIM6295_PIN7_HIGH) // clock frequency & pin 7 not verified
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.50)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.50)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
 
 	MCFG_SOUND_ADD("ymsnd", YM2413, XTAL_3_579545MHz)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.90)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.90)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.90)
 MACHINE_CONFIG_END
 
 static MACHINE_CONFIG_START( dokyusp, metro_state )
@@ -3996,15 +3981,13 @@ static MACHINE_CONFIG_START( dokyusp, metro_state )
 	MCFG_PALETTE_FORMAT(GGGGGRRRRRBBBBBx)
 
 	/* sound hardware */
-	MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
+	MCFG_SPEAKER_STANDARD_MONO("mono")
 
 	MCFG_OKIM6295_ADD("oki", 2112000, OKIM6295_PIN7_HIGH) // clock frequency & pin 7 not verified
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.50)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.50)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
 
 	MCFG_SOUND_ADD("ymsnd", YM2413, XTAL_3_579545MHz)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.90)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.90)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.90)
 MACHINE_CONFIG_END
 
 
@@ -4035,15 +4018,13 @@ static MACHINE_CONFIG_START( gakusai, metro_state )
 	MCFG_PALETTE_FORMAT(GGGGGRRRRRBBBBBx)
 
 	/* sound hardware */
-	MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
+	MCFG_SPEAKER_STANDARD_MONO("mono")
 
 	MCFG_OKIM6295_ADD("oki", 2112000, OKIM6295_PIN7_HIGH) // clock frequency & pin 7 not verified
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.25)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.25)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
 
 	MCFG_SOUND_ADD("ymsnd", YM2413, XTAL_3_579545MHz)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 2.00)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 2.00)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 2.00)
 MACHINE_CONFIG_END
 
 
@@ -4074,15 +4055,13 @@ static MACHINE_CONFIG_START( gakusai2, metro_state )
 	MCFG_PALETTE_FORMAT(GGGGGRRRRRBBBBBx)
 
 	/* sound hardware */
-	MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
+	MCFG_SPEAKER_STANDARD_MONO("mono")
 
 	MCFG_OKIM6295_ADD("oki", 2112000, OKIM6295_PIN7_HIGH) // clock frequency & pin 7 not verified
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.25)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.25)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
 
 	MCFG_SOUND_ADD("ymsnd", YM2413, XTAL_3_579545MHz)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 2.00)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 2.00)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 2.00)
 MACHINE_CONFIG_END
 
 
@@ -4114,17 +4093,15 @@ static MACHINE_CONFIG_START( pangpoms, metro_state )
 	MCFG_PALETTE_FORMAT(GGGGGRRRRRBBBBBx)
 
 	/* sound hardware */
-	MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
+	MCFG_SPEAKER_STANDARD_MONO("mono")
 
 	MCFG_GENERIC_LATCH_8_ADD("soundlatch")
 
 	MCFG_OKIM6295_ADD("oki", XTAL_24MHz/20, OKIM6295_PIN7_HIGH) // was /128.. so pin 7 not verified
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.10)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.10)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.10)
 
 	MCFG_SOUND_ADD("ymsnd", YM2413, XTAL_3_579545MHz)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.90)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.90)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.90)
 MACHINE_CONFIG_END
 
 
@@ -4156,17 +4133,15 @@ static MACHINE_CONFIG_START( poitto, metro_state )
 	MCFG_PALETTE_FORMAT(GGGGGRRRRRBBBBBx)
 
 	/* sound hardware */
-	MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
+	MCFG_SPEAKER_STANDARD_MONO("mono")
 
 	MCFG_GENERIC_LATCH_8_ADD("soundlatch")
 
 	MCFG_OKIM6295_ADD("oki", XTAL_24MHz/20, OKIM6295_PIN7_HIGH) // was /128.. so pin 7 not verified
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.10)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.10)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.10)
 
 	MCFG_SOUND_ADD("ymsnd", YM2413, XTAL_3_579545MHz)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.90)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.90)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.90)
 MACHINE_CONFIG_END
 
 
@@ -4198,18 +4173,16 @@ static MACHINE_CONFIG_START( pururun, metro_state )
 	MCFG_PALETTE_FORMAT(GGGGGRRRRRBBBBBx)
 
 	/* sound hardware */
-	MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
+	MCFG_SPEAKER_STANDARD_MONO("mono")
 
 	MCFG_GENERIC_LATCH_8_ADD("soundlatch")
 
 	MCFG_YM2151_ADD("ymsnd", XTAL_3_579545MHz)  /* Confirmed match to reference video */
 	MCFG_YM2151_IRQ_HANDLER(INPUTLINE("audiocpu", UPD7810_INTF2))
-	MCFG_SOUND_ROUTE(0, "lspeaker", 0.80)
-	MCFG_SOUND_ROUTE(1, "rspeaker", 0.80)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.80)
 
 	MCFG_OKIM6295_ADD("oki", XTAL_3_579545MHz/3, OKIM6295_PIN7_HIGH) // sample rate =  M6295 clock / 132
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.40)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.40)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.40)
 MACHINE_CONFIG_END
 
 
@@ -4241,17 +4214,15 @@ static MACHINE_CONFIG_START( skyalert, metro_state )
 	MCFG_PALETTE_FORMAT(GGGGGRRRRRBBBBBx)
 
 	/* sound hardware */
-	MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
+	MCFG_SPEAKER_STANDARD_MONO("mono")
 
 	MCFG_GENERIC_LATCH_8_ADD("soundlatch")
 
 	MCFG_OKIM6295_ADD("oki", XTAL_24MHz/20, OKIM6295_PIN7_LOW) // sample rate =  M6295 clock / 165
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.10)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.10)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.10)
 
 	MCFG_SOUND_ADD("ymsnd", YM2413, XTAL_3_579545MHz)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.90)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.90)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.90)
 MACHINE_CONFIG_END
 
 
@@ -4283,17 +4254,15 @@ static MACHINE_CONFIG_START( toride2g, metro_state )
 	MCFG_PALETTE_FORMAT(GGGGGRRRRRBBBBBx)
 
 	/* sound hardware */
-	MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
+	MCFG_SPEAKER_STANDARD_MONO("mono")
 
 	MCFG_GENERIC_LATCH_8_ADD("soundlatch")
 
 	MCFG_OKIM6295_ADD("oki", XTAL_24MHz/20, OKIM6295_PIN7_HIGH) // clock frequency & pin 7 not verified
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.10)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.10)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.10)
 
 	MCFG_SOUND_ADD("ymsnd", YM2413, XTAL_3_579545MHz)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.90)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.90)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.90)
 MACHINE_CONFIG_END
 
 
@@ -4322,15 +4291,13 @@ static MACHINE_CONFIG_START( mouja, metro_state )
 	MCFG_PALETTE_FORMAT(GGGGGRRRRRBBBBBx)
 
 	/* sound hardware */
-	MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
+	MCFG_SPEAKER_STANDARD_MONO("mono")
 	MCFG_OKIM6295_ADD("oki", XTAL_16MHz/1024*132, OKIM6295_PIN7_HIGH) // clock frequency & pin 7 not verified
 	MCFG_DEVICE_ADDRESS_MAP(AS_0, mouja_okimap)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.25)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.25)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
 
 	MCFG_SOUND_ADD("ymsnd", YM2413, XTAL_3_579545MHz)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 1.00)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 1.00)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
 MACHINE_CONFIG_END
 
 
@@ -4357,15 +4324,13 @@ static MACHINE_CONFIG_START( vmetal, metro_state )
 	MCFG_PALETTE_FORMAT(GGGGGRRRRRBBBBBx)
 
 	/* sound hardware */
-	MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
+	MCFG_SPEAKER_STANDARD_MONO("mono")
 
 	MCFG_OKIM6295_ADD("oki", XTAL_1MHz, OKIM6295_PIN7_HIGH)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.75)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.75)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.75)
 
 	MCFG_ES8712_ADD("essnd", 12000)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.50)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.50)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
 
 	// OKI M6585 not hooked up...
 MACHINE_CONFIG_END
@@ -4401,16 +4366,15 @@ static MACHINE_CONFIG_START( blzntrnd, metro_state )
 	MCFG_K053936_OFFSETS(-69, -21)
 
 	/* sound hardware */
-	MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
+	MCFG_SPEAKER_STANDARD_MONO("mono")
 
 	MCFG_GENERIC_LATCH_8_ADD("soundlatch")
 
 	MCFG_SOUND_ADD("ymsnd", YM2610, XTAL_16MHz/2)
 	MCFG_YM2610_IRQ_HANDLER(INPUTLINE("audiocpu", 0))
-	MCFG_SOUND_ROUTE(0, "lspeaker",  0.25)
-	MCFG_SOUND_ROUTE(0, "rspeaker", 0.25)
-	MCFG_SOUND_ROUTE(1, "lspeaker",  1.0)
-	MCFG_SOUND_ROUTE(2, "rspeaker", 1.0)
+	MCFG_SOUND_ROUTE(0, "mono", 0.25)
+	MCFG_SOUND_ROUTE(1, "mono", 1.0)
+	MCFG_SOUND_ROUTE(2, "mono", 1.0)
 MACHINE_CONFIG_END
 
 static MACHINE_CONFIG_DERIVED( gstrik2, blzntrnd )
@@ -4452,15 +4416,13 @@ static MACHINE_CONFIG_START( puzzlet, metro_state )
 	MCFG_PALETTE_FORMAT(GGGGGRRRRRBBBBBx)
 
 	/* sound hardware */
-	MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
+	MCFG_SPEAKER_STANDARD_MONO("mono")
 
 	MCFG_OKIM6295_ADD("oki", XTAL_20MHz/5, OKIM6295_PIN7_LOW)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.50)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.50)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
 
 	MCFG_SOUND_ADD("ymsnd", YM2413, XTAL_20MHz/5)
-	MCFG_SOUND_ROUTE(0, "lspeaker", 0.90)
-	MCFG_SOUND_ROUTE(1, "rspeaker", 0.90)
+	MCFG_SOUND_ROUTE(0, "mono", 0.90)
 MACHINE_CONFIG_END
 
 
diff --git a/src/mame/drivers/meyc8080.cpp b/src/mame/drivers/meyc8080.cpp
index d797f33..6888cf0 100644
--- a/src/mame/drivers/meyc8080.cpp
+++ b/src/mame/drivers/meyc8080.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina,Pierpaolo Prazzoli,hap,Roberto Fresca
 /**********************************************************
 
diff --git a/src/mame/drivers/micro20.cpp b/src/mame/drivers/micro20.cpp
old mode 100755
new mode 100644
index 6621b06..7b4c03c
--- a/src/mame/drivers/micro20.cpp
+++ b/src/mame/drivers/micro20.cpp
@@ -16,6 +16,7 @@
 #include "machine/msm58321.h"
 #include "machine/wd_fdc.h"
 #include "machine/68230pit.h"
+#include "bus/rs232/rs232.h"
 #include "softlist.h"
 
 #define MAINCPU_TAG "maincpu"
@@ -33,7 +34,8 @@ public:
 		m_maincpu(*this, MAINCPU_TAG),
 		m_rom(*this, "bootrom"),
 		m_mainram(*this, "mainram"),
-		m_pit(*this, PIT_TAG)
+		m_pit(*this, PIT_TAG),
+		m_rtc(*this, RTC_TAG)
 	{
 	}
 
@@ -41,14 +43,21 @@ public:
 	required_memory_region m_rom;
 	required_shared_ptr<uint32_t> m_mainram;
 	required_device<pit68230_device> m_pit;
+	required_device<msm58321_device> m_rtc;
 
 	virtual void machine_start() override;
 	virtual void machine_reset() override;
 
 	DECLARE_WRITE_LINE_MEMBER(m68k_reset_callback);
+	DECLARE_READ32_MEMBER(buserror_r);
 
-private:
+	TIMER_DEVICE_CALLBACK_MEMBER(micro20_timer);
+	DECLARE_WRITE_LINE_MEMBER(h4_w);
+	DECLARE_WRITE8_MEMBER(portb_w);
+	DECLARE_WRITE8_MEMBER(portc_w);
 
+private:
+	u8 m_tin;
 };
 
 void micro20_state::machine_start()
@@ -57,14 +66,27 @@ void micro20_state::machine_start()
 
 void micro20_state::machine_reset()
 {
-	uint32_t *pROM = (uint32_t *)m_rom->base();
-	uint32_t *pRAM = (uint32_t *)m_mainram.target();
+	u32 *pROM = (uint32_t *)m_rom->base();
+	u32 *pRAM = (uint32_t *)m_mainram.target();
 
-	pRAM[0] = pROM[0];
-	pRAM[1] = pROM[1];
+	pRAM[0] = pROM[2];
+	pRAM[1] = pROM[3];
 	m_maincpu->reset();
 
 	m_maincpu->set_reset_callback(write_line_delegate(FUNC(micro20_state::m68k_reset_callback),this));
+
+	m_tin = 0;
+}
+
+TIMER_DEVICE_CALLBACK_MEMBER(micro20_state::micro20_timer)
+{
+	m_pit->update_tin(m_tin);
+	m_tin ^= 1;
+}
+
+WRITE_LINE_MEMBER(micro20_state::h4_w)
+{
+	printf("h4_w: %d\n", state);
 }
 
 WRITE_LINE_MEMBER(micro20_state::m68k_reset_callback)
@@ -73,12 +95,40 @@ WRITE_LINE_MEMBER(micro20_state::m68k_reset_callback)
 	m_pit->reset();
 }
 
+WRITE8_MEMBER(micro20_state::portb_w)
+{
+	m_rtc->d0_w((data & 1) ? ASSERT_LINE : CLEAR_LINE);
+	m_rtc->d1_w((data & 2) ? ASSERT_LINE : CLEAR_LINE);
+	m_rtc->d2_w((data & 4) ? ASSERT_LINE : CLEAR_LINE);
+	m_rtc->d3_w((data & 8) ? ASSERT_LINE : CLEAR_LINE);
+}
+
+WRITE8_MEMBER(micro20_state::portc_w)
+{
+	// MSM58321 CS1 and CS2 are tied to /RST, inverted RESET.
+	// So they're always high when the system is not reset.
+	m_rtc->cs1_w(ASSERT_LINE);
+	m_rtc->cs2_w(ASSERT_LINE);
+	m_rtc->stop_w((data & 1) ? ASSERT_LINE : CLEAR_LINE);
+	m_rtc->write_w((data & 2) ? ASSERT_LINE : CLEAR_LINE);
+	m_rtc->read_w((data & 0x10) ? ASSERT_LINE : CLEAR_LINE);
+	m_rtc->address_write_w((data & 0x40) ? ASSERT_LINE : CLEAR_LINE);
+	m_rtc->test_w((data & 0x80) ? ASSERT_LINE : CLEAR_LINE);
+}
+
+READ32_MEMBER(micro20_state::buserror_r)
+{
+	m_maincpu->set_input_line(M68K_LINE_BUSERROR, ASSERT_LINE);
+	m_maincpu->set_input_line(M68K_LINE_BUSERROR, CLEAR_LINE);
+	return 0xffff;
+}
 /***************************************************************************
     ADDRESS MAPS
 ***************************************************************************/
 
 static ADDRESS_MAP_START(micro20_map, AS_PROGRAM, 32, micro20_state )
 	AM_RANGE(0x00000000, 0x001fffff) AM_RAM AM_SHARE("mainram")
+	AM_RANGE(0x00200000, 0x002fffff) AM_READ(buserror_r)
 	AM_RANGE(0x00800000, 0x0083ffff) AM_ROM AM_REGION("bootrom", 0)
 	AM_RANGE(0xffff8000, 0xffff8003) AM_DEVREADWRITE8(FDC_TAG, wd1772_t, status_r, cmd_w,    0xff000000)
 	AM_RANGE(0xffff8000, 0xffff8003) AM_DEVREADWRITE8(FDC_TAG, wd1772_t, track_r, track_w,   0x00ff0000)
@@ -95,18 +145,29 @@ static MACHINE_CONFIG_START( micro20, micro20_state )
 	MCFG_CPU_PROGRAM_MAP(micro20_map)
 
 	MCFG_MC68681_ADD(DUART_A_TAG, XTAL_3_6864MHz)
-//  MCFG_MC68681_IRQ_CALLBACK(WRITELINE(vt240_state, irq13_w))
-//  MCFG_MC68681_A_TX_CALLBACK(DEVWRITELINE("host", rs232_port_device, write_txd))
-//  MCFG_MC68681_B_TX_CALLBACK(DEVWRITELINE("printer", rs232_port_device, write_txd))
-//  MCFG_MC68681_OUTPORT_CALLBACK(WRITE8(vt240_state, duartout_w))
+	MCFG_MC68681_A_TX_CALLBACK(DEVWRITELINE("rs232", rs232_port_device, write_txd))
 
-	MCFG_MC68681_ADD(DUART_B_TAG, XTAL_3_6864MHz)
+	MCFG_RS232_PORT_ADD("rs232", default_rs232_devices, "terminal")
+	MCFG_RS232_RXD_HANDLER(DEVWRITELINE(DUART_A_TAG, mc68681_device, rx_a_w))
 
-	MCFG_DEVICE_ADD(RTC_TAG, MSM58321, XTAL_32_768kHz)
+	MCFG_MC68681_ADD(DUART_B_TAG, XTAL_3_6864MHz)
 
 	MCFG_WD1772_ADD(FDC_TAG, XTAL_16_67MHz / 2)
 
 	MCFG_DEVICE_ADD(PIT_TAG, PIT68230, XTAL_16_67MHz / 2)
+	MCFG_PIT68230_H4_CB(WRITELINE(micro20_state, h4_w))
+	MCFG_PIT68230_PB_OUTPUT_CB(WRITE8(micro20_state, portb_w))
+	MCFG_PIT68230_PC_OUTPUT_CB(WRITE8(micro20_state, portc_w))
+
+	MCFG_DEVICE_ADD(RTC_TAG, MSM58321, XTAL_32_768kHz)
+	MCFG_MSM58321_DEFAULT_24H(false)
+	MCFG_MSM58321_D0_HANDLER(DEVWRITELINE(PIT_TAG, pit68230_device, pb0_w))
+	MCFG_MSM58321_D1_HANDLER(DEVWRITELINE(PIT_TAG, pit68230_device, pb1_w))
+	MCFG_MSM58321_D2_HANDLER(DEVWRITELINE(PIT_TAG, pit68230_device, pb2_w))
+	MCFG_MSM58321_D3_HANDLER(DEVWRITELINE(PIT_TAG, pit68230_device, pb3_w))
+	MCFG_MSM58321_BUSY_HANDLER(DEVWRITELINE(PIT_TAG, pit68230_device, pb7_w))
+
+	MCFG_TIMER_DRIVER_ADD_PERIODIC("timer", micro20_state, micro20_timer, attotime::from_hz(200))
 MACHINE_CONFIG_END
 
 static INPUT_PORTS_START( micro20 )
diff --git a/src/mame/drivers/midwunit.cpp b/src/mame/drivers/midwunit.cpp
index b391b9d..d2c225c 100644
--- a/src/mame/drivers/midwunit.cpp
+++ b/src/mame/drivers/midwunit.cpp
@@ -125,7 +125,6 @@ static ADDRESS_MAP_START( main_map, AS_PROGRAM, 16, midwunit_state )
 ADDRESS_MAP_END
 
 
-
 /*************************************
  *
  *  Input ports
@@ -645,13 +644,26 @@ static MACHINE_CONFIG_START( wunit, midwunit_state )
 
 	MCFG_VIDEO_START_OVERRIDE(midwunit_state,midwunit)
 
-	MCFG_DEVICE_ADD("serial_pic", MIDWAY_SERIAL_PIC, 0)
-	MCFG_MIDWAY_SERIAL_PIC_UPPER(528);
-
 	/* sound hardware */
 	MCFG_DEVICE_ADD("dcs", DCS_AUDIO_8K, 0)
 MACHINE_CONFIG_END
 
+static MACHINE_CONFIG_DERIVED( wunit_picsim, wunit )
+	MCFG_DEVICE_ADD("serial_security_sim", MIDWAY_SERIAL_PIC, 0)
+	MCFG_MIDWAY_SERIAL_PIC_UPPER(528); // this is actually a generic code all games check for in addition to their own game specific code!
+MACHINE_CONFIG_END
+
+
+static MACHINE_CONFIG_DERIVED( wunit_picemu, wunit )
+	MCFG_DEVICE_ADD("serial_security", MIDWAY_SERIAL_PIC_EMU, 0)
+
+	// todo, REMOVE once the emulated PIC above works!
+	// this just allows it to fall through to the simulation for now
+	MCFG_DEVICE_ADD("serial_security_sim", MIDWAY_SERIAL_PIC, 0)
+	MCFG_MIDWAY_SERIAL_PIC_UPPER(528);
+
+MACHINE_CONFIG_END
+
 
 
 /*************************************
@@ -827,6 +839,9 @@ ROM_START( umk3 )
 	ROM_LOAD16_BYTE( "um312u54.bin",  0x00000, 0x80000, CRC(712b4db6) SHA1(7015a55f3d745c6aeb8630903e2d5cd9554b2766) )
 	ROM_LOAD16_BYTE( "um312u63.bin",  0x00001, 0x80000, CRC(6d301faf) SHA1(18a8e29cc3e8ce5cc0e10f8386d43e7f44fd7b75) )
 
+	ROM_REGION( 0x1009, "serial_security:pic", 0 )   /* security PIC (provides game ID code and serial number) */
+	ROM_LOAD( "463 MK3 Ultimate.u64",  0x0000, 0x1009, CRC(4f425218) SHA1(7f26045ed2c9ca94fadcb673ce10f28208aa720e) )
+
 	ROM_REGION( 0x2000000, "gfxrom", 0 )
 	ROM_LOAD32_BYTE( "mk3-u133.bin",  0x0000000, 0x100000, CRC(79b94667) SHA1(31bba640c351fdccc6685cadb74dd79a3f910ce8) )
 	ROM_LOAD32_BYTE( "mk3-u132.bin",  0x0000001, 0x100000, CRC(13e95228) SHA1(405b05f5a5a55667c2be17d4b399129bdacefd90) )
@@ -866,6 +881,9 @@ ROM_START( umk3r11 )
 	ROM_LOAD16_BYTE( "um311u54.bin",  0x00000, 0x80000, CRC(8bb27659) SHA1(a3ffe3d8f21c261b36c7510d620d691a8bbf665b) )
 	ROM_LOAD16_BYTE( "um311u63.bin",  0x00001, 0x80000, CRC(ea731783) SHA1(2915626090650c4b5adf5b26e736c3ec91ce81a6) )
 
+	ROM_REGION( 0x1009, "serial_security:pic", 0 )   /* security PIC (provides game ID code and serial number) */
+	ROM_LOAD( "463 MK3 Ultimate.u64",  0x0000, 0x1009, CRC(4f425218) SHA1(7f26045ed2c9ca94fadcb673ce10f28208aa720e) )
+
 	ROM_REGION( 0x2000000, "gfxrom", 0 )
 	ROM_LOAD32_BYTE( "mk3-u133.bin",  0x0000000, 0x100000, CRC(79b94667) SHA1(31bba640c351fdccc6685cadb74dd79a3f910ce8) )
 	ROM_LOAD32_BYTE( "mk3-u132.bin",  0x0000001, 0x100000, CRC(13e95228) SHA1(405b05f5a5a55667c2be17d4b399129bdacefd90) )
@@ -905,6 +923,9 @@ ROM_START( umk3r10 )
 	ROM_LOAD16_BYTE( "um310u54.bin",  0x00000, 0x80000, CRC(dfd735da) SHA1(bcb6d80dbde407d0042ec2f225b2f98740a79203) )
 	ROM_LOAD16_BYTE( "um310u63.bin",  0x00001, 0x80000, CRC(2dff0c83) SHA1(8942ffa3addf134085ea8d77d56e82593312e7a5) )
 
+	ROM_REGION( 0x1009, "serial_security:pic", 0 )   /* security PIC (provides game ID code and serial number) */
+	ROM_LOAD( "463 MK3 Ultimate.u64",  0x0000, 0x1009, CRC(4f425218) SHA1(7f26045ed2c9ca94fadcb673ce10f28208aa720e) )
+
 	ROM_REGION( 0x2000000, "gfxrom", 0 )
 	ROM_LOAD32_BYTE( "mk3-u133.bin",  0x0000000, 0x100000, CRC(79b94667) SHA1(31bba640c351fdccc6685cadb74dd79a3f910ce8) )
 	ROM_LOAD32_BYTE( "mk3-u132.bin",  0x0000001, 0x100000, CRC(13e95228) SHA1(405b05f5a5a55667c2be17d4b399129bdacefd90) )
@@ -1094,6 +1115,9 @@ ROM_START( rmpgwt )
 	ROM_LOAD16_BYTE( "1.3_rampage_world_u54_game.u54",  0x00000, 0x80000, CRC(2a8f6e1e) SHA1(7a87ad37fa1d1228c4cdd4704ff0aee42e9c86cb) )
 	ROM_LOAD16_BYTE( "1.3_rampage_world_u63_game.u63",  0x00001, 0x80000, CRC(403ae41e) SHA1(c08d9352efe63849f5d10c1bd1efe2b9dd7382e0) )
 
+	ROM_REGION( 0x1009, "serial_security:pic", 0 )   /* security PIC (provides game ID code and serial number) */
+	ROM_LOAD( "465 Rampage WT.u64",  0x0000, 0x1009, CRC(5c14d850) SHA1(f57aef8350e477252bff1fa0f930c1b5d0ceb03f) )
+
 	ROM_REGION( 0x2000000, "gfxrom", 0 )
 	ROM_LOAD32_BYTE( "1.0_rampage_world_tour_u133_image.u133",  0x0000000, 0x100000, CRC(5b5ac449) SHA1(1c01dde9a9dbd9f4a6cd30aea9f6410cab13c2c9) )
 	ROM_LOAD32_BYTE( "1.0_rampage_world_tour_u132_image.u132",  0x0000001, 0x100000, CRC(7b3f09c6) SHA1(477658481ee96d5ce462d5e198d80faff4d4352c) )
@@ -1128,6 +1152,9 @@ ROM_START( rmpgwt11 )
 	ROM_LOAD16_BYTE( "1.1_rampage_world_u54_game.u54",  0x00000, 0x80000, CRC(3aa514eb) SHA1(4ed8db55f257da6d872586d0f9f0cdf1c30e0d22) )
 	ROM_LOAD16_BYTE( "1.1_rampage_world_u63_game.u63",  0x00001, 0x80000, CRC(031c908f) SHA1(531669b13c33921ff199be1e841dd337c86fec50) )
 
+	ROM_REGION( 0x1009, "serial_security:pic", 0 )   /* security PIC (provides game ID code and serial number) */
+	ROM_LOAD( "465 Rampage WT.u64",  0x0000, 0x1009, CRC(5c14d850) SHA1(f57aef8350e477252bff1fa0f930c1b5d0ceb03f) )
+
 	ROM_REGION( 0x2000000, "gfxrom", 0 )
 	ROM_LOAD32_BYTE( "1.0_rampage_world_tour_u133_image.u133",  0x0000000, 0x100000, CRC(5b5ac449) SHA1(1c01dde9a9dbd9f4a6cd30aea9f6410cab13c2c9) )
 	ROM_LOAD32_BYTE( "1.0_rampage_world_tour_u132_image.u132",  0x0000001, 0x100000, CRC(7b3f09c6) SHA1(477658481ee96d5ce462d5e198d80faff4d4352c) )
@@ -1260,23 +1287,26 @@ ROM_END
  *
  *************************************/
 
-GAME( 1994, mk3,       0,        wunit, mk3,      midwunit_state, mk3,      ROT0, "Midway", "Mortal Kombat 3 (rev 2.1)", MACHINE_SUPPORTS_SAVE )
-GAME( 1994, mk3r20,    mk3,      wunit, mk3,      midwunit_state, mk3r20,   ROT0, "Midway", "Mortal Kombat 3 (rev 2.0)", MACHINE_SUPPORTS_SAVE )
-GAME( 1994, mk3r10,    mk3,      wunit, mk3,      midwunit_state, mk3r10,   ROT0, "Midway", "Mortal Kombat 3 (rev 1.0)", MACHINE_SUPPORTS_SAVE )
-GAME( 1994, mk3p40,    mk3,      wunit, mk3,      midwunit_state, mk3r10,   ROT0, "Midway", "Mortal Kombat 3 (rev 1 chip label p4.0)", MACHINE_SUPPORTS_SAVE )
-GAME( 1994, umk3,      0,        wunit, mk3,      midwunit_state, umk3,     ROT0, "Midway", "Ultimate Mortal Kombat 3 (rev 1.2)", MACHINE_SUPPORTS_SAVE )
-GAME( 1994, umk3r11,   umk3,     wunit, mk3,      midwunit_state, umk3r11,  ROT0, "Midway", "Ultimate Mortal Kombat 3 (rev 1.1)", MACHINE_SUPPORTS_SAVE )
-GAME( 1994, umk3r10,   umk3,     wunit, mk3,      midwunit_state, umk3r11,  ROT0, "Midway", "Ultimate Mortal Kombat 3 (rev 1.0)", MACHINE_SUPPORTS_SAVE )
+GAME( 1994, mk3,       0,        wunit_picsim, mk3,      midwunit_state, mk3,      ROT0, "Midway", "Mortal Kombat 3 (rev 2.1)", MACHINE_SUPPORTS_SAVE )
+GAME( 1994, mk3r20,    mk3,      wunit_picsim, mk3,      midwunit_state, mk3r20,   ROT0, "Midway", "Mortal Kombat 3 (rev 2.0)", MACHINE_SUPPORTS_SAVE )
+GAME( 1994, mk3r10,    mk3,      wunit_picsim, mk3,      midwunit_state, mk3r10,   ROT0, "Midway", "Mortal Kombat 3 (rev 1.0)", MACHINE_SUPPORTS_SAVE )
+GAME( 1994, mk3p40,    mk3,      wunit_picsim, mk3,      midwunit_state, mk3r10,   ROT0, "Midway", "Mortal Kombat 3 (rev 1 chip label p4.0)", MACHINE_SUPPORTS_SAVE )
+
+GAME( 1994, umk3,      0,        wunit_picemu, mk3,      midwunit_state, umk3,     ROT0, "Midway", "Ultimate Mortal Kombat 3 (rev 1.2)", MACHINE_SUPPORTS_SAVE )
+GAME( 1994, umk3r11,   umk3,     wunit_picemu, mk3,      midwunit_state, umk3r11,  ROT0, "Midway", "Ultimate Mortal Kombat 3 (rev 1.1)", MACHINE_SUPPORTS_SAVE )
+GAME( 1994, umk3r10,   umk3,     wunit_picemu, mk3,      midwunit_state, umk3r11,  ROT0, "Midway", "Ultimate Mortal Kombat 3 (rev 1.0)", MACHINE_SUPPORTS_SAVE )
 // Ultimate Mortal Kombat 3 rev 2.0.35 (TE? Hack?) version known to exist
 
-GAME( 1995, wwfmania,  0,        wunit, wwfmania, midwunit_state, wwfmania, ROT0, "Midway", "WWF: Wrestlemania (rev 1.30 08/10/95)", MACHINE_SUPPORTS_SAVE )
-GAME( 1995, wwfmaniab, wwfmania, wunit, wwfmania, midwunit_state, wwfmania, ROT0, "Midway", "WWF: Wrestlemania (rev 1.20 08/02/95)", MACHINE_SUPPORTS_SAVE )
-GAME( 1995, wwfmaniac, wwfmania, wunit, wwfmania, midwunit_state, wwfmania, ROT0, "Midway", "WWF: Wrestlemania (rev 1.1 07/11/95)", MACHINE_SUPPORTS_SAVE )
-GAME( 1995, openice,   0,        wunit, openice,  midwunit_state, openice,  ROT0, "Midway", "2 On 2 Open Ice Challenge (rev 1.21)", MACHINE_SUPPORTS_SAVE )
+GAME( 1995, wwfmania,  0,        wunit_picsim, wwfmania, midwunit_state, wwfmania, ROT0, "Midway", "WWF: Wrestlemania (rev 1.30 08/10/95)", MACHINE_SUPPORTS_SAVE )
+GAME( 1995, wwfmaniab, wwfmania, wunit_picsim, wwfmania, midwunit_state, wwfmania, ROT0, "Midway", "WWF: Wrestlemania (rev 1.20 08/02/95)", MACHINE_SUPPORTS_SAVE )
+GAME( 1995, wwfmaniac, wwfmania, wunit_picsim, wwfmania, midwunit_state, wwfmania, ROT0, "Midway", "WWF: Wrestlemania (rev 1.1 07/11/95)", MACHINE_SUPPORTS_SAVE )
+
+GAME( 1995, openice,   0,        wunit_picsim, openice,  midwunit_state, openice,  ROT0, "Midway", "2 On 2 Open Ice Challenge (rev 1.21)", MACHINE_SUPPORTS_SAVE )
+
+GAME( 1996, nbahangt,  0,        wunit_picsim, nbahangt, midwunit_state, nbahangt, ROT0, "Midway", "NBA Hangtime (rev L1.1 04/16/96)", MACHINE_SUPPORTS_SAVE )
 
-GAME( 1996, nbahangt,  0,        wunit, nbahangt, midwunit_state, nbahangt, ROT0, "Midway", "NBA Hangtime (rev L1.1 04/16/96)", MACHINE_SUPPORTS_SAVE )
-GAME( 1996, nbamht,    nbahangt, wunit, nbahangt, midwunit_state, nbahangt, ROT0, "Midway", "NBA Maximum Hangtime (rev 1.03 06/09/97)", MACHINE_SUPPORTS_SAVE )
-GAME( 1996, nbamht1,   nbahangt, wunit, nbahangt, midwunit_state, nbahangt, ROT0, "Midway", "NBA Maximum Hangtime (rev 1.0 11/08/96)", MACHINE_SUPPORTS_SAVE )
+GAME( 1996, nbamht,    0,        wunit_picsim, nbahangt, midwunit_state, nbahangt, ROT0, "Midway", "NBA Maximum Hangtime (rev 1.03 06/09/97)", MACHINE_SUPPORTS_SAVE )
+GAME( 1996, nbamht1,   nbamht,   wunit_picsim, nbahangt, midwunit_state, nbahangt, ROT0, "Midway", "NBA Maximum Hangtime (rev 1.0 11/08/96)", MACHINE_SUPPORTS_SAVE )
 
-GAME( 1997, rmpgwt,    0,        wunit, rmpgwt,   midwunit_state, rmpgwt,   ROT0, "Midway", "Rampage: World Tour (rev 1.3)", MACHINE_SUPPORTS_SAVE )
-GAME( 1997, rmpgwt11,  rmpgwt,   wunit, rmpgwt,   midwunit_state, rmpgwt,   ROT0, "Midway", "Rampage: World Tour (rev 1.1)", MACHINE_SUPPORTS_SAVE )
+GAME( 1997, rmpgwt,    0,        wunit_picemu, rmpgwt,   midwunit_state, rmpgwt,   ROT0, "Midway", "Rampage: World Tour (rev 1.3)", MACHINE_SUPPORTS_SAVE )
+GAME( 1997, rmpgwt11,  rmpgwt,   wunit_picemu, rmpgwt,   midwunit_state, rmpgwt,   ROT0, "Midway", "Rampage: World Tour (rev 1.1)", MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/drivers/mitchell.cpp b/src/mame/drivers/mitchell.cpp
index a00456d..8f6c676 100644
--- a/src/mame/drivers/mitchell.cpp
+++ b/src/mame/drivers/mitchell.cpp
@@ -363,13 +363,18 @@ static ADDRESS_MAP_START( spangbl_map, AS_PROGRAM, 8, mitchell_state )
 	AM_RANGE(0xe000, 0xffff) AM_RAM AM_SHARE("ram")     /* Work RAM */
 ADDRESS_MAP_END
 
+WRITE8_MEMBER(mitchell_state::sound_command_w)
+{
+	m_soundlatch->write(space, 0, data);
+	m_audiocpu->set_input_line(0, HOLD_LINE);
+}
+
 static ADDRESS_MAP_START( spangbl_io_map, AS_IO, 8, mitchell_state )
 	ADDRESS_MAP_GLOBAL_MASK(0xff)
 	AM_RANGE(0x00, 0x02) AM_READ(input_r)
 	AM_RANGE(0x00, 0x00) AM_WRITE(pangbl_gfxctrl_w)    /* Palette bank, layer enable, coin counters, more */
 	AM_RANGE(0x02, 0x02) AM_WRITE(pang_bankswitch_w)      /* Code bank register */
-	AM_RANGE(0x03, 0x03) AM_DEVWRITE("ymsnd", ym2413_device, data_port_w)
-	AM_RANGE(0x04, 0x04) AM_DEVWRITE("ymsnd", ym2413_device, register_port_w)
+	AM_RANGE(0x03, 0x03) AM_WRITE(sound_command_w)
 	AM_RANGE(0x05, 0x05) AM_READ_PORT("SYS0")
 	AM_RANGE(0x06, 0x06) AM_WRITENOP    /* watchdog? irq ack? */
 	AM_RANGE(0x07, 0x07) AM_WRITE(pang_video_bank_w)      /* Video RAM bank register */
@@ -378,22 +383,37 @@ static ADDRESS_MAP_START( spangbl_io_map, AS_IO, 8, mitchell_state )
 	AM_RANGE(0x18, 0x18) AM_WRITE(eeprom_serial_w)
 ADDRESS_MAP_END
 
+READ8_MEMBER(mitchell_state::sound_command_r)
+{
+	m_audiocpu->set_input_line(0, CLEAR_LINE);
+	return m_soundlatch->read(space, 0);
+}
 
-#ifdef UNUSED_FUNCTION
-WRITE8_MEMBER(mitchell_state::spangbl_msm5205_data_w)
+WRITE8_MEMBER(mitchell_state::sound_bankswitch_w)
 {
-	m_sample_buffer = data;
+	m_msm->reset_w(BIT(data, 3));
+
+	m_soundbank->set_entry(data & 7);
 }
-#endif
 
 static ADDRESS_MAP_START( spangbl_sound_map, AS_PROGRAM, 8, mitchell_state )
-	AM_RANGE(0x0000, 0x3fff) AM_ROM
-//  AM_RANGE(0xec00, 0xec00) AM_WRITE(spangbl_msm5205_data_w )
-	AM_RANGE(0xf000, 0xf3ff) AM_RAM
+	AM_RANGE(0x0000, 0x7fff) AM_ROM
+	AM_RANGE(0x8000, 0xbfff) AM_ROMBANK("soundbank")
+	AM_RANGE(0xe000, 0xe000) AM_WRITE(sound_bankswitch_w)
+	AM_RANGE(0xe400, 0xe400) AM_DEVWRITE("adpcm_select", ls157_device, ba_w)
+	AM_RANGE(0xec00, 0xec01) AM_DEVWRITE("ymsnd", ym2413_device, write)
+	AM_RANGE(0xf000, 0xf4ff) AM_RAM
+	AM_RANGE(0xf800, 0xf800) AM_READ(sound_command_r)
 ADDRESS_MAP_END
 
-static ADDRESS_MAP_START( spangbl_sound_io_map, AS_IO, 8, mitchell_state )
-	ADDRESS_MAP_GLOBAL_MASK(0xff)
+static ADDRESS_MAP_START( pangba_sound_map, AS_PROGRAM, 8, mitchell_state )
+	AM_RANGE(0x0000, 0x7fff) AM_ROM
+	AM_RANGE(0x8000, 0xbfff) AM_ROMBANK("soundbank")
+	AM_RANGE(0xe000, 0xe000) AM_WRITE(sound_bankswitch_w)
+	AM_RANGE(0xe400, 0xe400) AM_DEVWRITE("adpcm_select", ls157_device, ba_w)
+	AM_RANGE(0xec00, 0xec01) AM_DEVWRITE("ymsnd", ym3812_device, write)
+	AM_RANGE(0xf000, 0xf4ff) AM_RAM
+	AM_RANGE(0xf800, 0xf800) AM_READ(sound_command_r)
 ADDRESS_MAP_END
 
 
@@ -1101,20 +1121,25 @@ GFXDECODE_END
 
 MACHINE_START_MEMBER(mitchell_state,mitchell)
 {
-	save_item(NAME(m_sample_buffer));
-	save_item(NAME(m_sample_select));
 	save_item(NAME(m_dial_selected));
 	save_item(NAME(m_keymatrix));
 	save_item(NAME(m_dir));
 	save_item(NAME(m_dial));
 	save_item(NAME(m_irq_source));
 //  save_item(NAME(init_eeprom_count));
+
+	if (m_soundbank.found())
+	{
+		m_soundbank->configure_entries(0, 8, memregion("audiocpu")->base(), 0x4000);
+		m_soundbank->set_entry(0);
+
+		save_item(NAME(m_sample_select));
+	}
 }
 
 MACHINE_RESET_MEMBER(mitchell_state,mitchell)
 {
-	m_sample_buffer = 0;
-	m_sample_select = 0;
+	m_sample_select = false;
 	m_dial_selected = 0;
 	m_dial[0] = 0;
 	m_dial[1] = 0;
@@ -1241,11 +1266,12 @@ GFXDECODE_END
 
 WRITE_LINE_MEMBER(mitchell_state::spangbl_adpcm_int)
 {
-	m_msm->data_w(m_sample_buffer & 0x0f);
-	m_sample_buffer >>= 4;
-	m_sample_select ^= 1;
-	if(m_sample_select == 0)
-		m_audiocpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE);
+	if (!state)
+		return;
+
+	m_sample_select = !m_sample_select;
+	m_adpcm_select->select_w(m_sample_select);
+	m_audiocpu->set_input_line(INPUT_LINE_NMI, m_sample_select);
 }
 
 
@@ -1261,17 +1287,27 @@ static MACHINE_CONFIG_DERIVED( spangbl, pangnv )
 
 	MCFG_CPU_ADD("audiocpu", Z80, 8000000)
 	MCFG_CPU_PROGRAM_MAP(spangbl_sound_map)
-	MCFG_CPU_IO_MAP(spangbl_sound_io_map)
-	MCFG_CPU_VBLANK_INT_DRIVER("screen", mitchell_state,  irq0_line_hold)
-	MCFG_CPU_VBLANK_INT_DRIVER("screen", mitchell_state,  nmi_line_pulse)
 
 	MCFG_GFXDECODE_MODIFY("gfxdecode", spangbl)
 
+	MCFG_GENERIC_LATCH_8_ADD("soundlatch")
+
 	MCFG_DEVICE_REMOVE("oki")
 	MCFG_SOUND_ADD("msm", MSM5205, 384000)
 	MCFG_MSM5205_VCLK_CB(WRITELINE(mitchell_state, spangbl_adpcm_int))  /* interrupt function */
 	MCFG_MSM5205_PRESCALER_SELECTOR(MSM5205_S48_4B)      /* 4KHz 4-bit */
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
+
+	MCFG_DEVICE_ADD("adpcm_select", LS157, 0)
+	MCFG_74157_OUT_CB(DEVWRITE8("msm", msm5205_device, data_w))
+MACHINE_CONFIG_END
+
+static MACHINE_CONFIG_DERIVED( pangba, spangbl )
+	MCFG_CPU_MODIFY("audiocpu")
+	MCFG_CPU_PROGRAM_MAP(pangba_sound_map)
+
+	MCFG_DEVICE_REPLACE("ymsnd", YM3812, 4000000)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
 MACHINE_CONFIG_END
 
 static MACHINE_CONFIG_START( mstworld, mitchell_state )
@@ -2365,14 +2401,14 @@ GAME( 1989, bbros,     pang,     pang,      pang,     mitchell_state, pang,
 GAME( 1989, pompingw,  pang,     pang,      pang,     mitchell_state, pang,      ROT0,   "Mitchell",                  "Pomping World (Japan)", MACHINE_SUPPORTS_SAVE )
 GAME( 1989, pangb,     pang,     pang,      pang,     mitchell_state, pangb,     ROT0,   "bootleg",                   "Pang (bootleg, set 1)", MACHINE_SUPPORTS_SAVE )
 GAME( 1989, pangbold,  pang,     pang,      pang,     mitchell_state, pangb,     ROT0,   "bootleg",                   "Pang (bootleg, set 2)", MACHINE_SUPPORTS_SAVE )
-GAME( 1989, pangba,    pang,     spangbl,   pang,     mitchell_state, pangb,     ROT0,   "bootleg",                   "Pang (bootleg, set 3)", MACHINE_NO_SOUND | MACHINE_SUPPORTS_SAVE )
+GAME( 1989, pangba,    pang,     pangba,    pang,     mitchell_state, pangb,     ROT0,   "bootleg",                   "Pang (bootleg, set 3)", MACHINE_SUPPORTS_SAVE )
 GAME( 1989, pangb2,    pang,     pang,      pang,     mitchell_state, pangb,     ROT0,   "bootleg",                   "Pang (bootleg, set 4)", MACHINE_SUPPORTS_SAVE )
 GAME( 1989, cworld,    0,        pang,      qtono1,   mitchell_state, cworld,    ROT0,   "Capcom",                    "Capcom World (Japan)", MACHINE_SUPPORTS_SAVE )
 GAME( 1990, hatena,    0,        pang,      qtono1,   mitchell_state, hatena,    ROT0,   "Capcom",                    "Adventure Quiz 2 - Hatena? no Daibouken (Japan 900228)", MACHINE_SUPPORTS_SAVE )
 GAME( 1990, spang,     0,        pangnv,    pang,     mitchell_state, spang,     ROT0,   "Mitchell",                  "Super Pang (World 900914)", MACHINE_SUPPORTS_SAVE )
 GAME( 1990, sbbros,    spang,    pangnv,    pang,     mitchell_state, sbbros,    ROT0,   "Mitchell (Capcom license)", "Super Buster Bros. (USA 901001)", MACHINE_SUPPORTS_SAVE )
 GAME( 1990, spangj,    spang,    pangnv,    pang,     mitchell_state, spangj,    ROT0,   "Mitchell",                  "Super Pang (Japan 901023)", MACHINE_SUPPORTS_SAVE )
-GAME( 1990, spangbl,   spang,    spangbl,   spangbl,  mitchell_state, spangbl,   ROT0,   "bootleg",                   "Super Pang (World 900914, bootleg)", MACHINE_NO_SOUND | MACHINE_SUPPORTS_SAVE ) // different sound hardware
+GAME( 1990, spangbl,   spang,    spangbl,   spangbl,  mitchell_state, spangbl,   ROT0,   "bootleg",                   "Super Pang (World 900914, bootleg)", MACHINE_SUPPORTS_SAVE ) // different sound hardware
 GAME( 1994, mstworld,  0,        mstworld,  mstworld, mitchell_state, mstworld,  ROT0,   "bootleg (TCH)",             "Monsters World (bootleg of Super Pang)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
 GAME( 1990, marukin,   0,        marukin,   marukin,  mitchell_state, marukin,   ROT0,   "Yuga",                      "Super Marukin-Ban (Japan 901017)", MACHINE_SUPPORTS_SAVE )
 GAME( 1991, qtono1,    0,        pang,      qtono1,   mitchell_state, qtono1,    ROT0,   "Capcom",                    "Quiz Tonosama no Yabou (Japan)", MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/drivers/mmodular.cpp b/src/mame/drivers/mmodular.cpp
index 1a95011..10ccbc0 100644
--- a/src/mame/drivers/mmodular.cpp
+++ b/src/mame/drivers/mmodular.cpp
@@ -1796,22 +1796,22 @@ DRIVER_INIT_MEMBER(polgar_state,polgar)
 
 /*       YEAR  NAME      PARENT   COMPAT  MACHINE    INPUT     INIT     COMPANY                      FULLNAME                     FLAGS */
 	CONS(  1986, polgar,   0,       0,      polgar,    polgar, polgar_state,   polgar,  "Hegener & Glaser",          "Mephisto Polgar Schachcomputer", MACHINE_NOT_WORKING | MACHINE_REQUIRES_ARTWORK | MACHINE_CLICKABLE_ARTWORK)
-	CONS(  1987, sfortea,  0,       0,      sfortea,   sfortea, driver_device,  0,       "Novag",                     "Novag Super Forte Chess Computer (version A)", MACHINE_NO_SOUND|MACHINE_NOT_WORKING|MACHINE_NOT_WORKING | MACHINE_CLICKABLE_ARTWORK )
+	CONS(  1987, sfortea,  0,       0,      sfortea,   sfortea, driver_device,  0,       "Novag",                     "Novag Super Forte Chess Computer (version A)", MACHINE_NO_SOUND|MACHINE_NOT_WORKING | MACHINE_CLICKABLE_ARTWORK )
 	CONS(  1988, alm16,    van16,   0,      alm16,     van16, driver_device,    0,       "Hegener & Glaser Muenchen", "Mephisto Almeria 68000", MACHINE_NOT_WORKING|MACHINE_REQUIRES_ARTWORK | MACHINE_CLICKABLE_ARTWORK )
 	CONS(  1988, alm32,    van16,   0,      alm32,     van32, driver_device,    0,       "Hegener & Glaser Muenchen", "Mephisto Alimera 68020", MACHINE_NOT_WORKING|MACHINE_REQUIRES_ARTWORK | MACHINE_CLICKABLE_ARTWORK )
-	CONS(  1988, sforteb,  sfortea, 0,      sfortea,   sfortea, driver_device,  0,       "Novag",                     "Novag Super Forte Chess Computer (version B)", MACHINE_NO_SOUND|MACHINE_NOT_WORKING|MACHINE_NOT_WORKING | MACHINE_CLICKABLE_ARTWORK )
-	CONS(  1988, sforteba, sfortea, 0,      sfortea,   sfortea, driver_device,  0,       "Novag",                     "Novag Super Forte Chess Computer (version B, alt)", MACHINE_NO_SOUND|MACHINE_NOT_WORKING|MACHINE_NOT_WORKING | MACHINE_CLICKABLE_ARTWORK )
-	CONS(  1988, sexpertb, sfortea, 0,      sfortea,   sfortea, driver_device,  0,       "Novag",                     "Novag Super Expert B Chess Computer", MACHINE_NO_SOUND|MACHINE_NOT_WORKING|MACHINE_NOT_WORKING | MACHINE_CLICKABLE_ARTWORK )
+	CONS(  1988, sforteb,  sfortea, 0,      sfortea,   sfortea, driver_device,  0,       "Novag",                     "Novag Super Forte Chess Computer (version B)", MACHINE_NO_SOUND|MACHINE_NOT_WORKING | MACHINE_CLICKABLE_ARTWORK )
+	CONS(  1988, sforteba, sfortea, 0,      sfortea,   sfortea, driver_device,  0,       "Novag",                     "Novag Super Forte Chess Computer (version B, alt)", MACHINE_NO_SOUND|MACHINE_NOT_WORKING | MACHINE_CLICKABLE_ARTWORK )
+	CONS(  1988, sexpertb, sfortea, 0,      sfortea,   sfortea, driver_device,  0,       "Novag",                     "Novag Super Expert B Chess Computer", MACHINE_NO_SOUND|MACHINE_NOT_WORKING | MACHINE_CLICKABLE_ARTWORK )
 	CONS(  1989, academy,  0,       0,      academy,   academy, driver_device,  0,       "Hegener & Glaser",          "Mephisto Academy Schachcomputer", MACHINE_REQUIRES_ARTWORK|MACHINE_NOT_WORKING | MACHINE_CLICKABLE_ARTWORK )
-	CONS(  1989, megaiv,   0,       0,      megaiv,    megaiv, driver_device,   0,       "Hegener & Glaser",          "Mephisto Mega IV Schachcomputer", MACHINE_NOT_WORKING|MACHINE_NOT_WORKING|MACHINE_REQUIRES_ARTWORK | MACHINE_CLICKABLE_ARTWORK )
+	CONS(  1989, megaiv,   0,       0,      megaiv,    megaiv, driver_device,   0,       "Hegener & Glaser",          "Mephisto Mega IV Schachcomputer", MACHINE_NOT_WORKING|MACHINE_REQUIRES_ARTWORK | MACHINE_CLICKABLE_ARTWORK )
 	CONS(  1989, milano,   polgar,  0,      milano,    polgar, polgar_state,   polgar,  "Hegener & Glaser",          "Mephisto Milano Schachcomputer", MACHINE_REQUIRES_ARTWORK | MACHINE_CLICKABLE_ARTWORK )
-//CONS(  1989, montec4,  0,       0,      monteciv,  monteciv, driver_device, 0,       "Hegener & Glaser",          "Mephisto Monte Carlo IV", MACHINE_NOT_WORKING|MACHINE_NOT_WORKING|MACHINE_REQUIRES_ARTWORK | MACHINE_CLICKABLE_ARTWORK )
-	CONS(  1989, sfortec,  sfortea, 0,      sfortea,   sfortea, driver_device,  0,       "Novag",                     "Novag Super Forte Chess Computer (version C)", MACHINE_NO_SOUND|MACHINE_NOT_WORKING|MACHINE_NOT_WORKING | MACHINE_CLICKABLE_ARTWORK )
-	CONS(  1989, sexpertc, sfortea, 0,      sfortea,   sfortea, driver_device,  0,       "Novag",                     "Novag Super Expert C Chess Computer", MACHINE_NO_SOUND|MACHINE_NOT_WORKING|MACHINE_NOT_WORKING | MACHINE_CLICKABLE_ARTWORK )
+//CONS(  1989, montec4,  0,       0,      monteciv,  monteciv, driver_device, 0,       "Hegener & Glaser",          "Mephisto Monte Carlo IV", MACHINE_NOT_WORKING|MACHINE_REQUIRES_ARTWORK | MACHINE_CLICKABLE_ARTWORK )
+	CONS(  1989, sfortec,  sfortea, 0,      sfortea,   sfortea, driver_device,  0,       "Novag",                     "Novag Super Forte Chess Computer (version C)", MACHINE_NO_SOUND|MACHINE_NOT_WORKING | MACHINE_CLICKABLE_ARTWORK )
+	CONS(  1989, sexpertc, sfortea, 0,      sfortea,   sfortea, driver_device,  0,       "Novag",                     "Novag Super Expert C Chess Computer", MACHINE_NO_SOUND|MACHINE_NOT_WORKING | MACHINE_CLICKABLE_ARTWORK )
 	CONS(  1990, lyon16,   van16,   0,      alm16,     van16, driver_device,    0,       "Hegener & Glaser Muenchen", "Mephisto Lyon 68000", MACHINE_NOT_WORKING|MACHINE_REQUIRES_ARTWORK | MACHINE_CLICKABLE_ARTWORK )
 	CONS(  1990, lyon32,   van16,   0,      alm32,     van32, driver_device,    0,       "Hegener & Glaser Muenchen", "Mephisto Lyon 68020", MACHINE_NOT_WORKING|MACHINE_REQUIRES_ARTWORK | MACHINE_CLICKABLE_ARTWORK )
-	CONS(  1990, monteciv, 0,       0,      monteciv,  monteciv, driver_device, 0,       "Hegener & Glaser",          "Mephisto Monte Carlo IV LE Schachcomputer", MACHINE_NOT_WORKING|MACHINE_NOT_WORKING|MACHINE_REQUIRES_ARTWORK | MACHINE_CLICKABLE_ARTWORK )
-	CONS(  1991, diablo68, 0,       0,      diablo68,  sfortea, driver_device,  0,       "Novag",                     "Novag Diablo 68000 Chess Computer", MACHINE_NO_SOUND|MACHINE_NOT_WORKING|MACHINE_NOT_WORKING | MACHINE_CLICKABLE_ARTWORK )
+	CONS(  1990, monteciv, 0,       0,      monteciv,  monteciv, driver_device, 0,       "Hegener & Glaser",          "Mephisto Monte Carlo IV LE Schachcomputer", MACHINE_NOT_WORKING|MACHINE_REQUIRES_ARTWORK | MACHINE_CLICKABLE_ARTWORK )
+	CONS(  1991, diablo68, 0,       0,      diablo68,  sfortea, driver_device,  0,       "Novag",                     "Novag Diablo 68000 Chess Computer", MACHINE_NO_SOUND|MACHINE_NOT_WORKING | MACHINE_CLICKABLE_ARTWORK )
 	CONS(  1991, van16,    0,       0,      van16,     van16, driver_device,    0,       "Hegener & Glaser Muenchen", "Mephisto Vancouver 68000", MACHINE_NOT_WORKING|MACHINE_REQUIRES_ARTWORK | MACHINE_CLICKABLE_ARTWORK )
 	CONS(  1991, van32,    van16,   0,      van32,     van32, driver_device,    0,       "Hegener & Glaser Muenchen", "Mephisto Vancouver 68020", MACHINE_NOT_WORKING|MACHINE_REQUIRES_ARTWORK | MACHINE_CLICKABLE_ARTWORK )
 	CONS(  1993, gen32,    van16,   0,      gen32,     gen32, driver_device,    0,       "Hegener & Glaser Muenchen", "Mephisto Genius030 V4.00", MACHINE_NOT_WORKING|MACHINE_REQUIRES_ARTWORK | MACHINE_CLICKABLE_ARTWORK )
diff --git a/src/mame/drivers/model1.cpp b/src/mame/drivers/model1.cpp
index dc9f1a5..02f8c8a 100644
--- a/src/mame/drivers/model1.cpp
+++ b/src/mame/drivers/model1.cpp
@@ -1059,7 +1059,7 @@ static INPUT_PORTS_START( vr )
 	PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_UNUSED )
 	PORT_BIT( 0xff00, IP_ACTIVE_LOW, IPT_UNKNOWN )
 
-	PORT_START("IN.2")
+	PORT_START("IN.2")   /* 8Bit RX-line from drive board */
 	PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED )
 	PORT_BIT( 0xff00, IP_ACTIVE_LOW, IPT_UNKNOWN )
 INPUT_PORTS_END
@@ -1096,7 +1096,7 @@ static INPUT_PORTS_START( wingwar )
 	PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_UNUSED )
 	PORT_BIT( 0xff00, IP_ACTIVE_LOW, IPT_UNKNOWN )
 
-	PORT_START("IN.2")
+	PORT_START("IN.2")   /* 8Bit RX-line from r360 board */
 	PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED )
 	PORT_BIT( 0xff00, IP_ACTIVE_LOW, IPT_UNKNOWN )
 INPUT_PORTS_END
@@ -1668,12 +1668,76 @@ static MACHINE_CONFIG_START( model1_vr, model1_state )
 	MCFG_M1COMM_ADD("m1comm")
 MACHINE_CONFIG_END
 
-GAME( 1993, vf,         0,       model1,    vf, driver_device,       0, ROT0, "Sega", "Virtua Fighter", MACHINE_IMPERFECT_GRAPHICS )
-GAMEL(1992, vr,         0,       model1_vr, vr, driver_device,       0, ROT0, "Sega", "Virtua Racing", MACHINE_IMPERFECT_GRAPHICS, layout_vr )
-GAME( 1993, vformula,   vr,      model1_vr, vr, driver_device,       0, ROT0, "Sega", "Virtua Formula", MACHINE_IMPERFECT_GRAPHICS )
-GAME( 1993, swa,        0,       swa,       swa, driver_device,      0, ROT0, "Sega", "Star Wars Arcade", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND )
-GAME( 1994, wingwar,    0,       model1,    wingwar, driver_device,  0, ROT0, "Sega", "Wing War (World)", MACHINE_NOT_WORKING )
-GAME( 1994, wingwaru,   wingwar, model1,    wingwar, driver_device,  0, ROT0, "Sega", "Wing War (US)", MACHINE_NOT_WORKING )
-GAME( 1994, wingwarj,   wingwar, model1,    wingwar, driver_device,  0, ROT0, "Sega", "Wing War (Japan)", MACHINE_NOT_WORKING )
-GAME( 1994, wingwar360, wingwar, model1,    wingwar, driver_device,  0, ROT0, "Sega", "Wing War R360 (US)", MACHINE_NOT_WORKING )
-GAME( 1993, netmerc,    0,       model1,    vf, driver_device,       0, ROT0, "Sega", "NetMerc?", MACHINE_NOT_WORKING )
+DRIVER_INIT_MEMBER(model1_state,wingwar360)
+{
+	// install r360 hack
+	m_maincpu->space(AS_PROGRAM).install_read_handler(0xc00014, 0xc00015, read16_delegate(FUNC(model1_state::r360_r),this));
+	m_maincpu->space(AS_PROGRAM).install_write_handler(0xc00022, 0xc00023, write16_delegate(FUNC(model1_state::r360_w),this));
+}
+
+READ16_MEMBER(model1_state::r360_r)
+{
+	return m_r360_state;
+}
+
+WRITE16_MEMBER(model1_state::r360_w)
+{
+	/*
+	    this uses the feedback board protocol
+	    command group B - these seem to be gamestates
+
+	    bf = init
+	    be = attract
+	    bd = setup #1 (lower safety bar etc.)
+	    bc = setup #2 (push emergency button)
+	    bb = ready to go
+	    ba = ingame
+	    b9 = game over
+
+	    results:
+	    40 = default status
+	    41 = * (setup #1 ack)
+	    42 = lowered safety bar
+	    43 = closed belt
+	    44 = lever up
+	    45 = pushed button
+	    46 = game start
+	    47 = game over
+	    48 = lever down
+	    49 = released belt
+	*/
+	switch (data & 0xff)
+	{
+		case 0xbf:
+		case 0xbe:
+			m_r360_state = ~0x40;
+			break;
+
+		case 0xbd:
+			m_r360_state = ~0x44;
+			break;
+
+		case 0xbc:
+			m_r360_state = ~0x45;
+			break;
+
+		case 0xbb:
+			m_r360_state = ~0x46;
+			break;
+
+		case 0xba:
+		case 0xb9:
+			m_r360_state = ~0x40;
+			break;
+	}
+}
+
+GAME( 1993, vf,         0,       model1,    vf, driver_device,      0,          ROT0, "Sega", "Virtua Fighter", MACHINE_IMPERFECT_GRAPHICS )
+GAMEL(1992, vr,         0,       model1_vr, vr, driver_device,      0,          ROT0, "Sega", "Virtua Racing", MACHINE_IMPERFECT_GRAPHICS, layout_vr )
+GAME( 1993, vformula,   vr,      model1_vr, vr, driver_device,      0,          ROT0, "Sega", "Virtua Formula", MACHINE_IMPERFECT_GRAPHICS )
+GAME( 1993, swa,        0,       swa,       swa, driver_device,     0,          ROT0, "Sega", "Star Wars Arcade", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND )
+GAME( 1994, wingwar,    0,       model1,    wingwar, driver_device, 0,          ROT0, "Sega", "Wing War (World)", MACHINE_NOT_WORKING )
+GAME( 1994, wingwaru,   wingwar, model1,    wingwar, driver_device, 0,          ROT0, "Sega", "Wing War (US)", MACHINE_NOT_WORKING )
+GAME( 1994, wingwarj,   wingwar, model1,    wingwar, driver_device, 0,          ROT0, "Sega", "Wing War (Japan)", MACHINE_NOT_WORKING )
+GAME( 1994, wingwar360, wingwar, model1,    wingwar, model1_state,  wingwar360, ROT0, "Sega", "Wing War R360 (US)", MACHINE_NOT_WORKING )
+GAME( 1993, netmerc,    0,       model1,    vf, driver_device,      0,          ROT0, "Sega", "NetMerc?", MACHINE_NOT_WORKING )
diff --git a/src/mame/drivers/model2.cpp b/src/mame/drivers/model2.cpp
index 94b37e4..5be07f6 100644
--- a/src/mame/drivers/model2.cpp
+++ b/src/mame/drivers/model2.cpp
@@ -752,14 +752,42 @@ WRITE32_MEMBER(model2_state::copro_function_port_w)
 	//logerror("copro_function_port_w: %08X, %08X, %08X\n", data, offset, mem_mask);
 	if (m_dsp_type == DSP_TYPE_SHARC)
 		copro_fifoin_push(machine().device("dsp"), d,offset,mem_mask);
-	else
+	else if (m_dsp_type == DSP_TYPE_TGP)
 		copro_fifoin_push(machine().device("tgp"), d,offset,mem_mask);
+	else if (m_dsp_type == DSP_TYPE_TGPX4)
+	{
+		if (m_tgpx4->is_fifoin_full())
+			printf("trying to push to full fifo! (function port)\n");
+
+		m_tgpx4->fifoin_w(d);
+	}
 }
 
 READ32_MEMBER(model2_state::copro_fifo_r)
 {
 	//logerror("copro_fifo_r: %08X, %08X\n", offset, mem_mask);
-	return copro_fifoout_pop(space,offset,mem_mask);
+	if (m_dsp_type == DSP_TYPE_SHARC || m_dsp_type == DSP_TYPE_TGP)
+	{
+		return copro_fifoout_pop(space, offset, mem_mask);
+	}
+	else
+	{
+		// TODO
+//      printf("FIFO OUT read\n");
+		if (m_tgpx4->is_fifoout0_empty())
+		{
+			/* Reading from empty FIFO causes the i960 to enter wait state */
+			downcast<i960_cpu_device &>(space.device()).i960_stall();
+			/* spin the main cpu and let the TGP catch up */
+			space.device().execute().spin_until_time(attotime::from_usec(100));
+			printf("stalled\n");
+		}
+		else
+		{
+			return (uint32_t)(m_tgpx4->fifoout0_r());
+		}
+	}
+	return 0;
 }
 
 WRITE32_MEMBER(model2_state::copro_fifo_w)
@@ -774,6 +802,19 @@ WRITE32_MEMBER(model2_state::copro_fifo_w)
 		{
 			m_tgp_program[m_coprocnt] = data;
 		}
+		else if (m_dsp_type == DSP_TYPE_TGPX4)
+		{
+			if (m_coprocnt & 1)
+			{
+				m_tgpx4_program[m_coprocnt / 2] &= 0xffffffffU;
+				m_tgpx4_program[m_coprocnt / 2] |= u64(data) << 32;
+			}
+			else
+			{
+				m_tgpx4_program[m_coprocnt / 2] &= 0xffffffff00000000U;
+				m_tgpx4_program[m_coprocnt / 2] |= data;
+			}
+		}
 
 		m_coprocnt++;
 	}
@@ -785,8 +826,24 @@ WRITE32_MEMBER(model2_state::copro_fifo_w)
 		//osd_printf_debug("copro_fifo_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, space.device().safe_pc());
 		if (m_dsp_type == DSP_TYPE_SHARC)
 			copro_fifoin_push(machine().device("dsp"), data,offset,mem_mask);
-		else
+		else if (m_dsp_type == DSP_TYPE_TGP)
 			copro_fifoin_push(machine().device("tgp"), data,offset,mem_mask);
+		else if (m_dsp_type == DSP_TYPE_TGPX4)
+		{
+			if (m_tgpx4->is_fifoin_full())
+			{
+				/* Writing to full FIFO causes the i960 to enter wait state */
+				downcast<i960_cpu_device &>(space.device()).i960_stall();
+				/* spin the main cpu and let the TGP catch up */
+				space.device().execute().spin_until_time(attotime::from_usec(100));
+				printf("write stalled\n");
+			}
+			else
+			{
+//              printf("push %08X at %08X\n", data, space.device().safe_pc());
+				m_tgpx4->fifoin_w(data);
+			}
+		}
 	}
 }
 
@@ -1624,7 +1681,8 @@ static ADDRESS_MAP_START( model2c_crx_mem, AS_PROGRAM, 32, model2_state )
 	AM_RANGE(0x00200000, 0x0023ffff) AM_RAM
 
 	AM_RANGE(0x00804000, 0x00807fff) AM_READWRITE(geo_prg_r, geo_prg_w)
-	AM_RANGE(0x00884000, 0x00887fff) AM_READWRITE(copro_prg_r, copro_prg_w)
+	AM_RANGE(0x00880000, 0x00883fff) AM_WRITE(copro_function_port_w)
+	AM_RANGE(0x00884000, 0x00887fff) AM_READWRITE(copro_fifo_r, copro_fifo_w)
 
 	AM_RANGE(0x00980000, 0x00980003) AM_READWRITE(copro_ctl1_r,copro_ctl1_w)
 	AM_RANGE(0x00980008, 0x0098000b) AM_WRITE(geo_ctl1_w )
@@ -3099,7 +3157,7 @@ ROM_START( srallycb ) /* Sega Rally Championship Revision B, Model 2A, Sega game
 	MODEL2A_VID_BOARD
 ROM_END
 
-ROM_START( srallyca ) /* Sega Rally Championship DX Revision A, Model 2A - Single player cabinet - NO LINK option!, Sega ROM board ID# 834-11254 RALLY 50 */
+ROM_START( srallycdx ) /* Sega Rally Championship DX Revision A, Model 2A - Single player cabinet - NO LINK option!, Sega ROM board ID# 834-11254 RALLY 50 */
 	ROM_REGION( 0x200000, "maincpu", 0 ) // i960 program
 	ROM_LOAD32_WORD( "epr-17760a.12",  0x000000, 0x020000, CRC(2c1b996b) SHA1(28c1196aac1c242e61069ee809c9e8229c061950) ) /* AMD 27C1024 EPROM */
 	ROM_LOAD32_WORD( "epr-17761a.13",  0x000002, 0x020000, CRC(50813f66) SHA1(f27ffb314e06fa18d863fdf172dafe56122cd606) ) /* AMD 27C1024 EPROM */
@@ -3109,7 +3167,7 @@ ROM_START( srallyca ) /* Sega Rally Championship DX Revision A, Model 2A - Singl
 	ROM_LOAD32_WORD( "mpr-17747.11", 0x000002, 0x200000, CRC(543593fd) SHA1(5ba63a77e9fc70569af21d50b3171bc8ff4522b8) )
 	ROM_LOAD32_WORD( "mpr-17744.8",  0x400000, 0x200000, CRC(71fed098) SHA1(1d187cad375121a45348d640edd3cc7dce658d28) )
 	ROM_LOAD32_WORD( "mpr-17745.9",  0x400002, 0x200000, CRC(8ecca705) SHA1(ed2b3298aad6f4e52dc672a0168183e457564b43) )
-	ROM_LOAD32_WORD( "mpr-17764a.6", 0x800000, 0x200000, CRC(dcb91e31) SHA1(2725268e97b9f4c14d56c040af38bc82f5020e3e) )
+	ROM_LOAD32_WORD( "mpr-17764a.6", 0x800000, 0x200000, CRC(dcb91e31) SHA1(2725268e97b9f4c14d56c040af38bc82f5020e3e) ) // IC 6 and 7 likely EPROMs
 	ROM_LOAD32_WORD( "mpr-17765a.7", 0x800002, 0x200000, CRC(b657dc48) SHA1(ae0f1bc6e2479fa51ca36f8be3a1785981c4dfe9) )
 
 	ROM_REGION( 0x800000, "tgp", 0 ) // TGP program? (COPRO socket)
@@ -3149,6 +3207,56 @@ ROM_START( srallyca ) /* Sega Rally Championship DX Revision A, Model 2A - Singl
 	MODEL2A_VID_BOARD
 ROM_END
 
+ROM_START( srallycdxa ) // Sega Rally Championship DX, Model 2A? - Single player cabinet - NO LINK option!
+	ROM_REGION( 0x200000, "maincpu", 0 ) // i960 program
+	ROM_LOAD32_WORD( "epr-17760.12",  0x000000, 0x020000, CRC(2b5c4321) SHA1(5bcdd8cdfd8f3a95062f83be4a417ba999b50e47) ) // AMD 27C1024 EPROM
+	ROM_LOAD32_WORD( "epr-17761.13",  0x000002, 0x020000, CRC(50813f66) SHA1(f27ffb314e06fa18d863fdf172dafe56122cd606) ) // AMD 27C1024 EPROM
+
+	ROM_REGION32_LE( 0x2400000, "user1", 0 ) // Data
+	ROM_LOAD32_WORD( "mpr-17746.10", 0x000000, 0x200000, CRC(8fe311f4) SHA1(f4ada8e5c906fc384bed1b96f09cdf313f89e825) )
+	ROM_LOAD32_WORD( "mpr-17747.11", 0x000002, 0x200000, CRC(543593fd) SHA1(5ba63a77e9fc70569af21d50b3171bc8ff4522b8) )
+	ROM_LOAD32_WORD( "mpr-17744.8",  0x400000, 0x200000, CRC(71fed098) SHA1(1d187cad375121a45348d640edd3cc7dce658d28) )
+	ROM_LOAD32_WORD( "mpr-17745.9",  0x400002, 0x200000, CRC(8ecca705) SHA1(ed2b3298aad6f4e52dc672a0168183e457564b43) )
+	ROM_LOAD32_WORD( "epr-17764.6",  0x800000, 0x100000, CRC(68254fcf) SHA1(d90d962b5f81d6598fc9d94c44d9cee71767fc26) ) // NEC D27C8000D EPROM
+	ROM_LOAD32_WORD( "epr-17765.7",  0x800002, 0x100000, CRC(81112ea5) SHA1(a0251b4f5f18ae2e2d0576087a687dd7c2e49c34) ) // NEC D27C8000D EPROM
+
+	ROM_REGION( 0x800000, "tgp", 0 ) // TGP program? (COPRO socket)
+	ROM_LOAD32_WORD( "mpr-17754.28", 0x000000, 0x200000, CRC(81a84f67) SHA1(c0a9b690523a529e4015e9af10dc3fb2a1726f08) ) // not present in this rev memory test, why ?
+	ROM_LOAD32_WORD( "mpr-17755.29", 0x000002, 0x200000, CRC(2a6e7da4) SHA1(e60803ae951489fe47d66731d15c32249ca547b4) ) //
+
+	ROM_REGION( 0x010000, "drivecpu", 0 ) // Drive I/O program
+	ROM_LOAD( "epr-17762.ic12", 0x000000, 0x010000, NO_DUMP ) /* Need to verify actual EPR-xxxx number, might be EPR-17759 */
+	ROM_LOAD( "epr-17891.ic12", 0x000000, 0x010000, CRC(9a33b437) SHA1(3e8f210aa5159e78f640126cb5ce7f05f22560f2) ) /* REMOVE when EPR-17762 is dumped & added */
+
+	ROM_REGION( 0x2000000, "user2", 0 ) // Models
+	ROM_LOAD32_WORD( "mpr-17748.16", 0x000000, 0x200000, CRC(3148a2b2) SHA1(283cc49bfb6c6381a7ead9273fd097dca5b981b6) )
+	ROM_LOAD32_WORD( "mpr-17750.20", 0x000002, 0x200000, CRC(232aec29) SHA1(4d470e71df61298282c356814e2d151fda323fb6) )
+	ROM_LOAD32_WORD( "mpr-17749.17", 0x400000, 0x200000, CRC(0838d184) SHA1(704175c8b29e4c989afcb7be42e7e0e096740eaf) )
+	ROM_LOAD32_WORD( "mpr-17751.21", 0x400002, 0x200000, CRC(ed87ac62) SHA1(601542149d33ca52a47536b4b0af47bf1fd87eb2) )
+
+	ROM_REGION( 0x1000000, "user3", 0 ) // Textures
+	ROM_LOAD32_WORD( "mpr-17753.25", 0x000000, 0x200000, CRC(6db0eb36) SHA1(dd5fd3c9592360d3e95623ac2491e6faabe9dbcb) )
+	ROM_LOAD32_WORD( "mpr-17752.24", 0x000002, 0x200000, CRC(d6aa86ce) SHA1(1d342f87d1af1e5438d1ae818b1b14268e765897) )
+
+	ROM_REGION( 0x20000, "cpu4", 0) // Communication program
+	ROM_LOAD( "epr-16726.bin", 0x000000, 0x020000, CRC(c179b8c7) SHA1(86d3e65c77fb53b1d380b629348f4ab5b3d39228) )
+
+	ROM_REGION( 0x100000, "audiocpu", 0 ) // Sound program
+	ROM_LOAD16_WORD_SWAP( "epr-17763.30", 0x080000, 0x040000, NO_DUMP ) /* Number verified via Sega Rally Champ DX manual */
+	ROM_LOAD16_WORD_SWAP( "epr-17890a.30", 0x080000, 0x040000, CRC(5bac3fa1) SHA1(3635333d36463b6fab25560ed918e05138f964dc) ) /* REMOVE when EPR-17763 & EPR-17758 is dumped & added */
+
+	ROM_REGION( 0x800000, "scsp", 0 ) // Samples
+	ROM_LOAD( "mpr-17756.31", 0x000000, 0x200000, CRC(7725f111) SHA1(1f1ee3f19a6bcf57bc5a1c7dd64ee83f8b81f084) )
+	ROM_LOAD( "mpr-17757.32", 0x200000, 0x200000, CRC(1616e649) SHA1(1d3a0e441d150ada0535a9d50e2f69dd4b99c584) )
+	ROM_LOAD( "mpr-17758.36", 0x400000, 0x200000, NO_DUMP ) /* Number verified via Sega Rally Champ DX manual */
+	/* The DX version doesn't have any sound rom at IC37 */
+	ROM_LOAD( "mpr-17886.36", 0x400000, 0x200000, CRC(54a72923) SHA1(103c4838b27378c834c08d29d6fb6ba95e7f9d03) ) /* REMOVE when EPR-17758 & EPR-17763 is dumped & added */
+	ROM_LOAD( "mpr-17887.37", 0x600000, 0x200000, CRC(38c31fdd) SHA1(a85f05160b060d9d4a431aaa73cfc03f24214fb9) ) /* REMOVE when EPR-17758 & EPR-17763 is dumped & added */
+
+	MODEL2_CPU_BOARD
+	MODEL2A_VID_BOARD
+ROM_END
+
 /*
 
 Manx TT
@@ -4751,6 +4859,44 @@ ROM_START( overrevb ) /* Over Rev Revision B, Model 2B, rom board stickered as 8
 	ROM_LOAD( "mpr-20004.34", 0x400000, 0x400000, CRC(0b9c5410) SHA1(e5bb30702fc853ccc03316be07a334269d3ebb4a) )
 ROM_END
 
+ROM_START( rascot2 ) /* Royal Ascot 2, Model 2C, Rom Board : 837-12485 Com Board : 837-12532 SDC-2 */
+	ROM_REGION( 0x200000, "maincpu", 0 ) // i960 program
+	ROM_LOAD32_WORD("epr-20166.15",   0x000000, 0x020000, CRC(520479a4) SHA1(02e14a7be299c2af36373595cf6f154312372a60) )
+	ROM_LOAD32_WORD("epr-20167.16",   0x000002, 0x020000, CRC(e92f3d55) SHA1(a0b0df16484be0c45669982d87fe64a98f833549) )
+	ROM_LOAD32_WORD("epr-20164.13",   0x040000, 0x020000, CRC(576a15dc) SHA1(34e02d79b4e9c36e9dd441edc6e8d2afd589c558) )
+	ROM_LOAD32_WORD("epr-20165.14",   0x040002, 0x020000, CRC(7527f33b) SHA1(18c33173508ae43a2ab6a8f2d62e7735a6cd2898) )
+
+	ROM_REGION32_LE( 0x2000000, "user1", 0 ) // Data
+	ROM_LOAD32_WORD("mpr-20171.11",   0x000000, 0x400000, CRC(9f2327c6) SHA1(ed41d8b831bcf4dacbbd8bcaa92377cc95fc2a72) )
+	ROM_LOAD32_WORD("mpr-20172.12",   0x000002, 0x400000, CRC(40b4f8e6) SHA1(7d4a1d604205148c6d94c320e1d6438ab706fa67) )
+	ROM_LOAD32_WORD("mpr-20169.9",    0x800000, 0x400000, CRC(b5be4d6b) SHA1(cfb4696506efa0e93fab35bbeb87decd83aec040) )
+	ROM_LOAD32_WORD("mpr-20170.10",   0x800002, 0x400000, CRC(7b05cf33) SHA1(9e392ea0c7a9f4cef76d46ad92a7cf814022c133) )
+
+	ROM_REGION( 0x800000, "cpu2", ROMREGION_ERASE00) // TGPx4 program
+
+	ROM_REGION( 0x2000000, "user2", 0 ) // Models
+	ROM_LOAD32_WORD("mpr-20173.17",  0x0000000, 0x400000, CRC(60bd684e) SHA1(893985808adb88fb54f0ca85ca23995d65360360) )
+	ROM_LOAD32_WORD("mpr-20177.21",  0x0000002, 0x400000, CRC(4ba5199d) SHA1(5fa1cc56ec1d1c37d885c2d9a80fa93b9fbc4bce) )
+	ROM_LOAD32_WORD("mpr-20174.18",  0x0800000, 0x400000, CRC(6751ada5) SHA1(1ff61c133a93d3663d6a748b13ebb33285909314) )
+	ROM_LOAD32_WORD("mpr-20178.22",  0x0800002, 0x400000, CRC(f4fa00aa) SHA1(444805f403eac3b0377089176ead62aff7db7b96) )
+	ROM_LOAD32_WORD("mpr-20175.19",  0x1000000, 0x400000, CRC(801f4eff) SHA1(f5375b59c818841d77ab38317be0f7b9dbe14969) )
+	ROM_LOAD32_WORD("mpr-20179.23",  0x1000002, 0x400000, CRC(bd2c4e65) SHA1(bcc2f4cd37ebf4c36d00581e024281603d306123) )
+	ROM_LOAD32_WORD("mpr-20176.20",  0x1800000, 0x400000, CRC(50cb6b5a) SHA1(02c869cf874aa2310d60062e1e9b88ee26d7fa02) )
+	ROM_LOAD32_WORD("mpr-20180.24",  0x1800002, 0x400000, CRC(df16f2ca) SHA1(782a5ea3f713c47b55a9a5ecb5d36578977740a9) )
+
+	ROM_REGION( 0x1000000, "user3", 0 ) // Textures
+	ROM_LOAD32_WORD("mpr-20183.27",   0x000000, 0x400000, CRC(48520d72) SHA1(4519b497e20898e3aaa6398eb98cad990010a2fa) )
+	ROM_LOAD32_WORD("mpr-20181.25",   0x000002, 0x400000, CRC(99bfa480) SHA1(7176870b8fcc233440d31e1ca945fc4eb1dff204) )
+	ROM_LOAD32_WORD("mpr-20184.28",   0x800000, 0x400000, CRC(b8df0b12) SHA1(391c6aa40f2f6296ba3aa2a6ea2414ef2487f80c) )
+	ROM_LOAD32_WORD("mpr-20182.26",   0x800002, 0x400000, CRC(e3f085fe) SHA1(28efa84f6c04fbd285a9bcf6f651a57bfe54a507) )
+
+	ROM_REGION( 0x100000, "audiocpu", 0 ) // Sound program
+	ROM_LOAD16_WORD_SWAP("epr-20168.31",  0x080000, 0x020000, CRC(13a6a78d) SHA1(cbff422567b72d71607a42ea804c98b8c1e65824) )
+
+	ROM_REGION( 0x800000, "scsp", 0 ) // Samples
+	ROM_LOAD("epr-20185.32",  0x0000000, 0x200000, CRC(168cc361) SHA1(fbd2a9d99cc0afd7b5f0d9274916a0960d864118) )
+ROM_END
+
 ROM_START( topskatr ) /* Top Skater Revision A (Export), Model 2C, Sega Game ID# 833-13080-02, ROM board ID# 834-13081-02 */
 	ROM_REGION( 0x200000, "maincpu", 0 ) // i960 program
 	ROM_LOAD32_WORD("epr-19755a.15", 0x000000, 0x080000, CRC(b80633b9) SHA1(5396da414beeb918e6f38f25a43dd76345a0c8ed) )
@@ -4791,6 +4937,46 @@ ROM_START( topskatr ) /* Top Skater Revision A (Export), Model 2C, Sega Game ID#
 	ROM_LOAD("mpr-19750.24s", 0xc00000, 0x400000, CRC(cd95d0bf) SHA1(40e2a2980c89049c339fefd48bf7aac79962cd2e) )
 ROM_END
 
+ROM_START( topskatruo ) /* Top Skater (USA), Model 2C, Sega Game ID# 833-13080-01, ROM board ID# 834-13081-01 */
+	ROM_REGION( 0x200000, "maincpu", 0 ) // i960 program
+	ROM_LOAD32_WORD( "epr-19753.15", 0x000000, 0x080000, CRC(179a0954) SHA1(5d82455808e80ab6de615848fbefce7f4def12d0) )
+	ROM_LOAD32_WORD( "epr-19754.16", 0x000002, 0x080000, CRC(a4c62e01) SHA1(45ae0219a15b96f2283cd8e3df1940f6d48a3f63) )
+
+	ROM_REGION32_LE( 0x2000000, "user1", 0 ) // Data
+	ROM_LOAD32_WORD("mpr-19735.11",  0x000000, 0x400000, CRC(8e509266) SHA1(49afc91467f08befaf34e743cbe823de3e3c9d85) )
+	ROM_LOAD32_WORD("mpr-19736.12",  0x000002, 0x400000, CRC(094e0a0d) SHA1(de2c739f71e51166263446b9f6a566866ab8bee8) )
+	ROM_LOAD32_WORD("mpr-19737.9",   0x800000, 0x400000, CRC(281a7dde) SHA1(71d5ba434328a81969bfdc71ac1160c5ff3ae9d3) )
+	ROM_LOAD32_WORD("mpr-19738.10",  0x800002, 0x400000, CRC(f688327e) SHA1(68c9db242ef7e8f98979e968a09e4b093bc5d470) )
+
+	ROM_REGION( 0x800000, "cpu2", 0 ) // TGPx4 program
+	ROM_LOAD32_WORD("mpr-19743.29",  0x000000, 0x200000, CRC(d41a41bf) SHA1(a5f6b24e6526d0d2ef9c526c273c018d1e0fed59) )
+	ROM_LOAD32_WORD("mpr-19744.30",  0x000002, 0x200000, CRC(84f203bf) SHA1(4952b764e6bf6cd735018738c5eff08781ee2315) )
+
+	ROM_REGION( 0x400000, "user2", 0 ) // Models
+	ROM_LOAD32_WORD("mpr-19741.17",  0x000000, 0x200000, CRC(111a6e29) SHA1(8664059f157626e4bbdcf8357e3d30b37d3c25b8) )
+	ROM_LOAD32_WORD("mpr-19742.21",  0x000002, 0x200000, CRC(28510aff) SHA1(3e68aec090f36a60b3b70bc90f09e2f9ce088718) )
+
+	ROM_REGION( 0x800000, "user3", 0 ) // Textures
+	ROM_LOAD32_WORD("mpr-19740.27",  0x000000, 0x400000, CRC(b20f508b) SHA1(c90fa3b42d87291ea459ccc137f3a2f3eb7efec0) )
+	ROM_LOAD32_WORD("mpr-19739.25",  0x000002, 0x400000, CRC(8120cfd8) SHA1(a82744bff5dcdfae296c7c3e8c3fbfda26324e85) )
+
+	ROM_REGION( 0x100000, "audiocpu", 0 ) // Sound program
+	ROM_LOAD16_WORD_SWAP("mpr-19759.31", 0x080000,  0x80000, CRC(573530f2) SHA1(7b205085965d6694f8e75e29c4028f7cb6f631ab) )
+
+	ROM_REGION( 0x20000, "cpu3", 0) // DSB program
+	ROM_LOAD16_WORD_SWAP("mpr-19760.2s", 0x000000,  0x20000, CRC(2e41ca15) SHA1(a302209bfe0f1491dff2da64b32cfaa13c3d3304) )
+
+	ROM_REGION( 0x800000, "scsp", 0 ) // Samples
+	ROM_LOAD16_WORD_SWAP("mpr-19745.32", 0x000000, 0x400000, CRC(7082a0af) SHA1(415f9d0793a697cb1719bbd96370f4a741866527) )
+	ROM_LOAD16_WORD_SWAP("mpr-19746.34", 0x400000, 0x400000, CRC(657b5977) SHA1(ca76f211d68b6b55678a4d7949bfd2ddef1b1710) )
+
+	ROM_REGION( 0x1000000, "mpeg", 0 ) // MPEG audio data
+	ROM_LOAD("mpr-19747.18s", 0x000000, 0x400000, CRC(6e895aaa) SHA1(4c67c1e1d58a3034bbd711252a78689db9f235bb) )
+	ROM_LOAD("mpr-19748.20s", 0x400000, 0x400000, CRC(fcd74de3) SHA1(fd4da4cf40c4342c6263cf22eee5968292a4d2c0) )
+	ROM_LOAD("mpr-19749.22s", 0x800000, 0x400000, CRC(842ca1eb) SHA1(6ee6b2eb2ea400bdb9c0a9b4a126b4b86886e813) )
+	ROM_LOAD("mpr-19750.24s", 0xc00000, 0x400000, CRC(cd95d0bf) SHA1(40e2a2980c89049c339fefd48bf7aac79962cd2e) )
+ROM_END
+
 ROM_START( topskatru ) /* Top Skater Revision A (USA), Model 2C, Sega Game ID# 833-13080-01, ROM board ID# 834-13081-01 */
 	ROM_REGION( 0x200000, "maincpu", 0 ) // i960 program
 	ROM_LOAD32_WORD( "epr-19753a.15", 0x000000, 0x080000, CRC(3b3028de) SHA1(717ebf0ccd87128a24776e618cf15f07aaf48537) )
@@ -5918,9 +6104,10 @@ GAME( 1994, vcopa,        vcop, model2o, vcop,    driver_device, 0,        ROT0,
 // Model 2A-CRX (TGPs, SCSP sound board)
 GAME( 1995, manxtt,          0, manxttdx,     manxtt,   driver_device, 0,       ROT0, "Sega",   "Manx TT Superbike - DX (Revision D)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS )
 GAME( 1995, manxttc,         0, model2a,      manxtt,   driver_device, 0,       ROT0, "Sega",   "Manx TT Superbike - Twin (Revision C)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS )
-GAME( 1995, srallyc,         0, srallyc,      srallyc,  model2_state,  srallyc, ROT0, "Sega",   "Sega Rally Championship - TWIN (Revision C)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS )
-GAME( 1995, srallycb,  srallyc, srallyc,      srallyc,  model2_state,  srallyc, ROT0, "Sega",   "Sega Rally Championship - TWIN (Revision B)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS )
-GAME( 1995, srallyca,  srallyc, srallyc,      srallyc,  model2_state,  srallyc, ROT0, "Sega",   "Sega Rally Championship - DX (Revision A)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS )
+GAME( 1995, srallyc,         0, srallyc,      srallyc,  model2_state,  srallyc, ROT0, "Sega",   "Sega Rally Championship - TWIN/DX (Revision C)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS )
+GAME( 1995, srallycb,  srallyc, srallyc,      srallyc,  model2_state,  srallyc, ROT0, "Sega",   "Sega Rally Championship - TWIN/DX (Revision B)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS )
+GAME( 1995, srallycdx, srallyc, srallyc,      srallyc,  model2_state,  srallyc, ROT0, "Sega",   "Sega Rally Championship - DX (Revision A)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS )
+GAME( 1995, srallycdxa,srallyc, srallyc,      srallyc,  model2_state,  srallyc, ROT0, "Sega",   "Sega Rally Championship - DX", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS )
 GAME( 1995, vf2,             0, model2a,      model2,   driver_device, 0,       ROT0, "Sega",   "Virtua Fighter 2 (Version 2.1)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS )
 GAME( 1995, vf2b,          vf2, model2a,      model2,   driver_device, 0,       ROT0, "Sega",   "Virtua Fighter 2 (Revision B)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS )
 GAME( 1995, vf2a,          vf2, model2a,      model2,   driver_device, 0,       ROT0, "Sega",   "Virtua Fighter 2 (Revision A)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS )
@@ -5970,9 +6157,11 @@ GAME( 1996, stcca,        stcc,    stcc,      model2,  driver_device, 0,       R
 GAME( 1996, waverunr,        0, model2c,      model2,  driver_device, 0,       ROT0, "Sega",   "Wave Runner (Japan, Revision A)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS )
 GAME( 1997, hotd,            0, model2c,      model2,  driver_device, 0,       ROT0, "Sega",   "House of the Dead", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS )
 GAME( 1997, overrev,         0, model2c,      srallyc, driver_device, 0,       ROT0, "Jaleco", "Over Rev (Model 2C, Revision A)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS )
+GAME( 1997, rascot2,         0, model2c,      model2,  driver_device, 0,       ROT0, "Sega",   "Royal Ascot II", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS )
 GAME( 1997, segawski,        0, model2c,      model2,  driver_device, 0,       ROT0, "Sega",   "Sega Water Ski (Japan, Revision A)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS )
 GAME( 1997, topskatr,        0, model2c,      model2,  driver_device, 0,       ROT0, "Sega",   "Top Skater (Export, Revision A)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS )
 GAME( 1997, topskatru,topskatr, model2c,      model2,  driver_device, 0,       ROT0, "Sega",   "Top Skater (USA, Revision A)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS )
+GAME( 1997, topskatruo,topskatr,model2c,      model2,  driver_device, 0,       ROT0, "Sega",   "Top Skater (USA)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS )
 GAME( 1997, topskatrj,topskatr, model2c,      model2,  driver_device, 0,       ROT0, "Sega",   "Top Skater (Japan)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS )
 GAME( 1998, bel,             0, model2c,      bel,     driver_device, 0,       ROT0, "Sega / EPL Productions", "Behind Enemy Lines", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS )
 GAME( 1998, dynamcopc,dynamcop, model2c_5881, model2,  model2_state,  genprot, ROT0, "Sega",   "Dynamite Cop (USA, Model 2C)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_GRAPHICS )
diff --git a/src/mame/drivers/model3.cpp b/src/mame/drivers/model3.cpp
index 639e2f2..ec2f0e6 100644
--- a/src/mame/drivers/model3.cpp
+++ b/src/mame/drivers/model3.cpp
@@ -2251,10 +2251,10 @@ ROM_END
 ROM_START( scudj )  /* step 1.5, Sega game ID# is 833-13041, ROM board ID# 12934 SPG DX */
 	ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */
 	// CROM
-	ROM_LOAD64_WORD_SWAP( "epr-19610.17a",  0x0600006,  0x80000,  CRC(53f5cd94) SHA1(e27609165087ef7000b61ce628883561ffe64b22) )
-	ROM_LOAD64_WORD_SWAP( "epr-19609.18a",  0x0600004,  0x80000,  CRC(ec418b68) SHA1(8455db7e174ea00db30b7e61681ac7b7fcd9ba1c) )
-	ROM_LOAD64_WORD_SWAP( "epr-19608.19a",  0x0600002,  0x80000,  CRC(1426160e) SHA1(75cb61a94c7400df71bf38ba5fc9c2c972af7eaf) )
-	ROM_LOAD64_WORD_SWAP( "epr-19607.20a",  0x0600000,  0x80000,  CRC(24301a12) SHA1(5ef7bf9e72f3110b88e42c8fa42eb82008221e0e) )
+	ROM_LOAD64_WORD_SWAP( "epr-19610a.17",  0x0600006,  0x80000,  CRC(53f5cd94) SHA1(e27609165087ef7000b61ce628883561ffe64b22) )
+	ROM_LOAD64_WORD_SWAP( "epr-19609a.18",  0x0600004,  0x80000,  CRC(ec418b68) SHA1(8455db7e174ea00db30b7e61681ac7b7fcd9ba1c) )
+	ROM_LOAD64_WORD_SWAP( "epr-19608a.19",  0x0600002,  0x80000,  CRC(1426160e) SHA1(75cb61a94c7400df71bf38ba5fc9c2c972af7eaf) )
+	ROM_LOAD64_WORD_SWAP( "epr-19607a.20",  0x0600000,  0x80000,  CRC(24301a12) SHA1(5ef7bf9e72f3110b88e42c8fa42eb82008221e0e) )
 
 	// CROM0
 	ROM_LOAD64_WORD_SWAP( "mpr-19592.1",  0x0800006,  0x400000, CRC(d9003b6f) SHA1(c8242645619b1a02c29ca3f941461f163c9bf38f) )
@@ -3473,7 +3473,7 @@ ROM_START( vs298 )  /* Step 2.0, Sega ID# 833-13346, ROM board ID# 834-13347 */
 	ROM_PARAMETER( ":315_5881:key", "29234e96" )
 ROM_END
 
-ROM_START( vs29815 )    /* Step 1.5, ROM board ID# 834-13495 VS2 VER98 STEP 1.5 */
+ROM_START( vs29815 )    /* Step 1.5, Sega game ID# is 833-13494, ROM board ID# 834-13495 VS2 VER98 STEP 1.5 */
 	ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */
 	// CROM
 	ROM_LOAD64_WORD_SWAP( "epr-20909.17",  0x600006, 0x080000, CRC(3dff0d7e) SHA1(c6a6a103f499cd451796ae2480b8c38c3e87a143) )
@@ -3626,7 +3626,7 @@ ROM_START( vs2v991 )    /* Step 2.0 */
 	ROM_PARAMETER( ":315_5881:key", "29222ac8" )
 ROM_END
 
-ROM_START( vs299b ) /* Step 2.0 */
+ROM_START( vs299b ) /* Step 2.0, Sega game ID# is 833-13688, ROM board ID# 834-13689 VS2 VER99 STEP2 */
 	ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */
 	// CROM
 	ROM_LOAD64_WORD_SWAP( "epr-21550b.17",  0x400006, 0x100000, CRC(c508e488) SHA1(3134d418beaee9f824a0bd0e5441a997b5911d16) )
@@ -3860,7 +3860,82 @@ ROM_START( vs299 )  /* Step 2.0 */
 	ROM_PARAMETER( ":315_5881:key", "29222ac8" )
 ROM_END
 
-ROM_START( von2 )   /* Step 2.0 */
+ROM_START( vs29915 )  /* Step 1.5, Sega game ID# is 833-13686-01 VS2 VER99 STEP 1.5 JPN */
+	ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */
+	// CROM
+	ROM_LOAD64_WORD_SWAP( "epr-21531.17",  0x600006, 0x080000, CRC(ec45015c) SHA1(b3496da10111dfa505686c0bc8f0a30042d8a8e3) )
+	ROM_LOAD64_WORD_SWAP( "epr-21532.18",  0x600004, 0x080000, CRC(314447f8) SHA1(a623798037a4cae78161685ab95896e6641d7bd0) )
+	ROM_LOAD64_WORD_SWAP( "epr-21533.19",  0x600002, 0x080000, CRC(ea728471) SHA1(2a2541222152de43b8716b8ec86e258d96a9a0e3) )
+	ROM_LOAD64_WORD_SWAP( "epr-21534.20",  0x600000, 0x080000, CRC(d49ae219) SHA1(50e61c10bbdfe1609e3af0cd9cdf65859d6a18b9) )
+
+	// CROM0
+	ROM_LOAD64_WORD_SWAP( "mpr-21497.1",   0x800006, 0x400000, CRC(8ea759a1) SHA1(0d444fa360d93f48e5d6607362a231f97a7685d4) )
+	ROM_LOAD64_WORD_SWAP( "mpr-21498.2",   0x800004, 0x400000, CRC(4f53d6e0) SHA1(c8cd14f46d4ac7afdf55035a20d2e9a5ce2b6cde) )
+	ROM_LOAD64_WORD_SWAP( "mpr-21499.3",   0x800002, 0x400000, CRC(2cc4c1f1) SHA1(fd0fd747368e798095119a21d82f14778aeaa45e) )
+	ROM_LOAD64_WORD_SWAP( "mpr-21500.4",   0x800000, 0x400000, CRC(8c43964b) SHA1(cf3a6e9402f9ba532fca73f6838478558fb9a3ba) )
+
+	// CROM1
+	ROM_LOAD64_WORD_SWAP( "mpr-21501.5",  0x1800006, 0x400000, CRC(08bc2185) SHA1(6c4c977f68a73d605bdacdc0d76ca89bc7030c04) )
+	ROM_LOAD64_WORD_SWAP( "mpr-21502.6",  0x1800004, 0x400000, CRC(921486be) SHA1(bb1261272992cf86e83e0c788788765f05b43bbf) )
+	ROM_LOAD64_WORD_SWAP( "mpr-21503.7",  0x1800002, 0x400000, CRC(c9e1de6b) SHA1(d200c3da2c9bc6d4ed60dfa60a77056d25b19037) )
+	ROM_LOAD64_WORD_SWAP( "mpr-21504.8",  0x1800000, 0x400000, CRC(7aae557e) SHA1(2128d7dfa52e639858d37eb6100875b9ce3d056f) )
+
+	// CROM2
+	ROM_LOAD64_WORD_SWAP( "mpr-21505.9",  0x2800006, 0x400000, CRC(e169ff72) SHA1(9d407b424403261a224ea15b9476eba16406c4a4) )
+	ROM_LOAD64_WORD_SWAP( "mpr-21506.10", 0x2800004, 0x400000, CRC(2c1477c7) SHA1(81ab7d9cef5127e1f0e16f9a94a9ea2acc4530a4) )
+	ROM_LOAD64_WORD_SWAP( "mpr-21507.11", 0x2800002, 0x400000, CRC(1d8eb68b) SHA1(634693f066059c738526913498bb18be2f7cd086) )
+	ROM_LOAD64_WORD_SWAP( "mpr-21508.12", 0x2800000, 0x400000, CRC(2e8f798e) SHA1(8298df90101dd5850db8fccb7661ca2bc6806b3f) )
+
+	// CROM3
+	ROM_LOAD64_WORD_SWAP( "mpr-21509.13", 0x3800006, 0x400000, CRC(9a65e6b4) SHA1(e96c4bc2782b73490dffd5dcb11b9020077b11a3) )
+	ROM_LOAD64_WORD_SWAP( "mpr-21510.14", 0x3800004, 0x400000, CRC(f47489a4) SHA1(8412505002628d7ae3ab766a13e2068a018f3bf3) )
+	ROM_LOAD64_WORD_SWAP( "mpr-21511.15", 0x3800002, 0x400000, CRC(5ad9660c) SHA1(da387449292322a89af1cb6746d0fb8cea17575f) )
+	ROM_LOAD64_WORD_SWAP( "mpr-21512.16", 0x3800000, 0x400000, CRC(7cb2b05c) SHA1(16edc6642c74d9cef883559ca6ec562d985a43d6) )
+
+	// mirror CROM0 to CROM
+	ROM_COPY("user1", 0x800000, 0x000000, 0x600000)
+
+	ROM_REGION( 0x1000000, "user3", 0 )  /* Video ROMs Part 1 */
+	ROM_LOAD_VROM( "mpr-21515.26",     0x000002, 0x200000, CRC(8ce9910b) SHA1(7a0d0696e4456d9ebf131041917c5214b7d2e3ec) )
+	ROM_LOAD_VROM( "mpr-21516.27",     0x000000, 0x200000, CRC(8971a753) SHA1(00dfdb83a65f4fde337618c346157bb89f398531) )
+	ROM_LOAD_VROM( "mpr-21517.28",     0x000006, 0x200000, CRC(55a4533b) SHA1(b5701bbf7780bb9fc386cef4c1835606ab792f91) )
+	ROM_LOAD_VROM( "mpr-21518.29",     0x000004, 0x200000, CRC(4134026c) SHA1(2dfe1cbb354affe465c31a18c3ffb83a9bf555c9) )
+	ROM_LOAD_VROM( "mpr-21519.30",     0x00000a, 0x200000, CRC(ef6757de) SHA1(d41bbfcc551a4589bac577e311c67f2cba0a49aa) )
+	ROM_LOAD_VROM( "mpr-21520.31",     0x000008, 0x200000, CRC(c53be8cc) SHA1(b12dc0327a00b7e056254d2f11f96dbf396a0c91) )
+	ROM_LOAD_VROM( "mpr-21521.32",     0x00000e, 0x200000, CRC(abb501dc) SHA1(88cb40b0f795e0de1ff56e1f31bf834fad0c7885) )
+	ROM_LOAD_VROM( "mpr-21522.33",     0x00000c, 0x200000, CRC(e3b79973) SHA1(4b6ca16a23bb3e195ca60bee81b2d069f371ff70) )
+
+	ROM_REGION( 0x1000000, "user4", 0 )  /* Video ROMs Part 2 */
+	ROM_LOAD_VROM( "mpr-21523.34",     0x000002, 0x200000, CRC(fe4d1eac) SHA1(d222743d25ca92904ec212c66d03b3e3ff0ddbd9) )
+	ROM_LOAD_VROM( "mpr-21524.35",     0x000000, 0x200000, CRC(8633b6e9) SHA1(65ec24eb29613831dd28e5338cac14696b0d975d) )
+	ROM_LOAD_VROM( "mpr-21525.36",     0x000006, 0x200000, CRC(3c490167) SHA1(6fd46049723e0790b2231301cfa23071cd6ff1f6) )
+	ROM_LOAD_VROM( "mpr-21526.37",     0x000004, 0x200000, CRC(5fe5f9b0) SHA1(c708918cfc60f5fd9f6ec49ec1cd3167f2876e30) )
+	ROM_LOAD_VROM( "mpr-21527.38",     0x00000a, 0x200000, CRC(10d0fe7e) SHA1(63693b0de43e2eb6efbb3d2dfbe0e2f5bc6810dc) )
+	ROM_LOAD_VROM( "mpr-21528.39",     0x000008, 0x200000, CRC(4e346a6c) SHA1(ae34038d5bf6f63ec5ad2e8dd8e06db66147c40e) )
+	ROM_LOAD_VROM( "mpr-21529.40",     0x00000e, 0x200000, CRC(9a731a00) SHA1(eca98b142acc02fb28387675e1cb1bc7e4e59b86) )
+	ROM_LOAD_VROM( "mpr-21530.41",     0x00000c, 0x200000, CRC(78400d5e) SHA1(9b4546848dbe213f33b02e8ea42743e60a0f763f) )
+
+	ROM_REGION( 0x100000, "audiocpu", 0 )   /* 68000 code */
+	ROM_LOAD16_WORD_SWAP( "epr-21539.21", 0x080000, 0x080000, CRC(a1d3e00e) SHA1(e03bb31967929a12de9ae21923914e0e3bd96aaa) )
+
+	ROM_REGION( 0x800000, "samples", 0 )    /* SCSP samples */
+	ROM_LOAD( "mpr-21513.22", 0x000000, 0x400000, CRC(cca1cc00) SHA1(ba1fa3b8ef3bff7e116901a0a4bd80d2ae4018bf) )
+	ROM_LOAD( "mpr-21514.24", 0x400000, 0x400000, CRC(6cedd292) SHA1(c1f44715697a8bac9d39926bcd6558ec9a9b2319) )
+
+	ROM_REGION( 0x20000, "cpu2", 0 )    /* Z80 code */
+	ROM_FILL( 0x000000, 0x20000, 0x0000 )
+
+	ROM_REGION( 0x800000, "dsb", 0 )    /* DSB samples */
+	ROM_FILL( 0x000000, 0x800000, 0x0000 )
+
+	ROM_REGION( 0x80000, "scsp1", 0 )   /* first SCSP's RAM */
+	ROM_FILL( 0x000000, 0x80000, 0x0000 )
+
+	ROM_REGION( 0x80000, "scsp2", 0 )   /* second SCSP's RAM */
+	ROM_FILL( 0x000000, 0x80000, 0x0000 )
+ROM_END
+
+ROM_START( von2 )   /* Step 2.0, Sega game ID# is 833-13346, ROM board ID# 834-13347 VOT, Security board ID# 837-13379-COM */
 	ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */
 	// CROM
 	ROM_LOAD64_WORD_SWAP( "epr-20683b.17", 0x000006, 0x200000, CRC(59d9c974) SHA1(c45594ed474a9e8fd074e0d9d5fa6662bc88dee6) )
@@ -4304,10 +4379,10 @@ ROM_END
 ROM_START( dirtdvlsa )  /* Step 2.1 - Australia version */
 	ROM_REGION64_BE( 0x8800000, "user1", 0 ) /* program + data ROMs */
 	// CROM
-	ROM_LOAD64_WORD_SWAP( "epr-21058a", 0x000006, 0x200000, CRC(4d7fdc8d) SHA1(c45031b4e3ea65519de671e0e11f87e0965e3c93) )
-	ROM_LOAD64_WORD_SWAP( "epr-21059a", 0x000004, 0x200000, CRC(f31a2aa4) SHA1(b7398db217372885f763efdb909f3e43ccbac34a) )
-	ROM_LOAD64_WORD_SWAP( "epr-21060a", 0x000002, 0x200000, CRC(5ebe2816) SHA1(9ebbaf69f4a3b071d65ce3cbe6aabcd7547f1634) )
-	ROM_LOAD64_WORD_SWAP( "epr-21061a", 0x000000, 0x200000, CRC(755ca612) SHA1(ba21cf7f445bf1c33962affd0400247e27268233) )
+	ROM_LOAD64_WORD_SWAP( "epr-21058a.17", 0x000006, 0x200000, CRC(4d7fdc8d) SHA1(c45031b4e3ea65519de671e0e11f87e0965e3c93) )
+	ROM_LOAD64_WORD_SWAP( "epr-21059a.18", 0x000004, 0x200000, CRC(f31a2aa4) SHA1(b7398db217372885f763efdb909f3e43ccbac34a) )
+	ROM_LOAD64_WORD_SWAP( "epr-21060a.19", 0x000002, 0x200000, CRC(5ebe2816) SHA1(9ebbaf69f4a3b071d65ce3cbe6aabcd7547f1634) )
+	ROM_LOAD64_WORD_SWAP( "epr-21061a.20", 0x000000, 0x200000, CRC(755ca612) SHA1(ba21cf7f445bf1c33962affd0400247e27268233) )
 
 	// CROM0
 	ROM_LOAD64_WORD_SWAP( "mpr-21023.1",   0x800006, 0x400000, CRC(932a3724) SHA1(146dfe897caa8a4385c527bc7c649e9dbd2ce0c0) )
@@ -6153,6 +6228,7 @@ GAME( 1997, vs215,        vs2, model3_15, model3,   model3_state,    vs215, ROT0
 GAME( 1997, vs215o,       vs2, model3_15, model3,   model3_state,    vs215, ROT0, "Sega", "Virtua Striker 2 (Step 1.5, older)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND )
 GAME( 1997, lemans24,       0, model3_15, scud,     model3_state, lemans24, ROT0, "Sega", "Le Mans 24 (Revision B)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND )
 GAME( 1998, vs29815,    vs298, model3_15, model3,   model3_state,  vs29815, ROT0, "Sega", "Virtua Striker 2 '98 (Step 1.5)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND )
+GAME( 1999, vs29915,  vs2v991, model3_15, model3,   model3_state,    vs215, ROT0, "Sega", "Virtua Striker 2 '99 (Step 1.5)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND )
 
 /* Model 3 Step 2.0 */
 GAME( 1997, vs2,            0, model3_20,      model3,   model3_state,      vs2, ROT0, "Sega", "Virtua Striker 2 (Step 2.0)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND )
diff --git a/src/mame/drivers/momoko.cpp b/src/mame/drivers/momoko.cpp
index 1c7c46a..bcb9f87 100644
--- a/src/mame/drivers/momoko.cpp
+++ b/src/mame/drivers/momoko.cpp
@@ -253,11 +253,11 @@ void momoko_state::machine_reset()
 static MACHINE_CONFIG_START( momoko, momoko_state )
 
 	/* basic machine hardware */
-	MCFG_CPU_ADD("maincpu", Z80, 5000000)   /* 5.0MHz */
+	MCFG_CPU_ADD("maincpu", Z80, XTAL_10MHz/2)   /* 5.0MHz */
 	MCFG_CPU_PROGRAM_MAP(momoko_map)
 	MCFG_CPU_VBLANK_INT_DRIVER("screen", momoko_state,  irq0_line_hold)
 
-	MCFG_CPU_ADD("audiocpu", Z80, 2500000)  /* 2.5MHz */
+	MCFG_CPU_ADD("audiocpu", Z80, XTAL_10MHz/4)  /* 2.5MHz */
 	MCFG_CPU_PROGRAM_MAP(momoko_sound_map)
 
 	MCFG_WATCHDOG_ADD("watchdog")
@@ -281,13 +281,13 @@ static MACHINE_CONFIG_START( momoko, momoko_state )
 
 	MCFG_GENERIC_LATCH_8_ADD("soundlatch")
 
-	MCFG_SOUND_ADD("ym1", YM2203, 1250000)
+	MCFG_SOUND_ADD("ym1", YM2203, XTAL_10MHz/8)
 	MCFG_SOUND_ROUTE(0, "mono", 0.15)
 	MCFG_SOUND_ROUTE(1, "mono", 0.15)
 	MCFG_SOUND_ROUTE(2, "mono", 0.15)
 	MCFG_SOUND_ROUTE(3, "mono", 0.40)
 
-	MCFG_SOUND_ADD("ym2", YM2203, 1250000)
+	MCFG_SOUND_ADD("ym2", YM2203, XTAL_10MHz/8)
 	MCFG_AY8910_PORT_A_READ_CB(DEVREAD8("soundlatch", generic_latch_8_device, read))
 	MCFG_SOUND_ROUTE(0, "mono", 0.15)
 	MCFG_SOUND_ROUTE(1, "mono", 0.15)
@@ -299,43 +299,85 @@ MACHINE_CONFIG_END
 
 ROM_START( momoko )
 	ROM_REGION( 0x10000, "maincpu", 0 ) /* main CPU */
-	ROM_LOAD( "momoko03.bin", 0x0000,  0x8000, CRC(386e26ed) SHA1(ad746ed1b87bafc5b4df9a28aade58cf894f4e7b) )
-	ROM_LOAD( "momoko02.bin", 0x8000,  0x4000, CRC(4255e351) SHA1(27a0e8d8aea223d2128139582e3b66106f3608ef) )
+	ROM_LOAD( "momoko03.m6", 0x0000,  0x8000, CRC(386e26ed) SHA1(ad746ed1b87bafc5b4df9a28aade58cf894f4e7b) ) // age progression text in Japanese
+	ROM_LOAD( "momoko02.m5", 0x8000,  0x4000, CRC(4255e351) SHA1(27a0e8d8aea223d2128139582e3b66106f3608ef) )
 
 	ROM_REGION( 0x10000, "audiocpu", 0 ) /* sound CPU */
-	ROM_LOAD( "momoko01.bin", 0x0000,  0x8000, CRC(e8a6673c) SHA1(f8984b063929305c9058801202405e6d45254b5b) )
+	ROM_LOAD( "momoko01.u4", 0x0000,  0x8000, CRC(e8a6673c) SHA1(f8984b063929305c9058801202405e6d45254b5b) )
 
 	ROM_REGION( 0x2000, "gfx1", 0 ) /* text */
-	ROM_LOAD( "momoko13.bin", 0x0000,  0x2000, CRC(2745cf5a) SHA1(3db7c6319cac63df1620ef25508c5c45eaa4b141) )
+	ROM_LOAD( "momoko13.u4", 0x0000,  0x2000, CRC(2745cf5a) SHA1(3db7c6319cac63df1620ef25508c5c45eaa4b141) ) // On the FP-8631 PCB
 
 	ROM_REGION( 0x2000, "gfx3", 0 ) /* FG */
-	ROM_LOAD( "momoko14.bin", 0x0000,  0x2000, CRC(cfccca05) SHA1(4ecff488a37ac76ecb9ecf8980bea30dcc9c9951) )
+	ROM_LOAD( "momoko14.p2", 0x0000,  0x2000, CRC(cfccca05) SHA1(4ecff488a37ac76ecb9ecf8980bea30dcc9c9951) )
 
 	ROM_REGION( 0x10000, "gfx4", 0 ) /* sprite */
-	ROM_LOAD16_BYTE( "momoko16.bin", 0x0000,  0x8000, CRC(fc6876fc) SHA1(b2d06bc01ef9f4db9bf8902d67f31ccbb0fea61a) )
-	ROM_LOAD16_BYTE( "momoko17.bin", 0x0001,  0x8000, CRC(45dc0247) SHA1(1b2bd4197ab7d237966e037c249b5bd623646c0b) )
+	ROM_LOAD16_BYTE( "momoko16.e5", 0x0000,  0x8000, CRC(fc6876fc) SHA1(b2d06bc01ef9f4db9bf8902d67f31ccbb0fea61a) ) // On the FP-8631 PCB
+	ROM_LOAD16_BYTE( "momoko17.e6", 0x0001,  0x8000, CRC(45dc0247) SHA1(1b2bd4197ab7d237966e037c249b5bd623646c0b) ) // On the FP-8631 PCB
 
 	ROM_REGION( 0x20000, "gfx2", 0 ) /* BG */
-	ROM_LOAD16_BYTE( "momoko09.bin", 0x00000, 0x8000, CRC(9f5847c7) SHA1(6bc9a00622d8a23446294a8d5d467375c5719125) )
-	ROM_LOAD16_BYTE( "momoko11.bin", 0x00001, 0x8000, CRC(9c9fbd43) SHA1(7adfd7ea3dd6745c14e719883f1a86e0a3b3c0ff) )
-	ROM_LOAD16_BYTE( "momoko10.bin", 0x10000, 0x8000, CRC(ae17e74b) SHA1(f52657ea6b6ac518b70fd7b811d9699da27f67d9) )
-	ROM_LOAD16_BYTE( "momoko12.bin", 0x10001, 0x8000, CRC(1e29c9c4) SHA1(d78f102cefc9852b529dd317a76c7003ec2ad3d5) )
+	ROM_LOAD16_BYTE( "momoko09.e8", 0x00000, 0x8000, CRC(9f5847c7) SHA1(6bc9a00622d8a23446294a8d5d467375c5719125) )
+	ROM_LOAD16_BYTE( "momoko11.c8", 0x00001, 0x8000, CRC(9c9fbd43) SHA1(7adfd7ea3dd6745c14e719883f1a86e0a3b3c0ff) )
+	ROM_LOAD16_BYTE( "momoko10.d8", 0x10000, 0x8000, CRC(ae17e74b) SHA1(f52657ea6b6ac518b70fd7b811d9699da27f67d9) )
+	ROM_LOAD16_BYTE( "momoko12.a8", 0x10001, 0x8000, CRC(1e29c9c4) SHA1(d78f102cefc9852b529dd317a76c7003ec2ad3d5) )
 
 	ROM_REGION( 0x20000, "user1", 0 ) /* BG map */
-	ROM_LOAD( "momoko04.bin", 0x0000,  0x8000, CRC(3ab3c2c3) SHA1(d4a0d7f83bf64769e90a2c264c6114ac308cb8b5) )
-	ROM_LOAD( "momoko05.bin", 0x8000,  0x8000, CRC(757cdd2b) SHA1(3471b42dc6458a18894dbd0638f4fe43c86dd70d) )
-	ROM_LOAD( "momoko06.bin", 0x10000, 0x8000, CRC(20cacf8b) SHA1(e2b39abfc960e1c472e2bcf0cf06825c39941c03) )
-	ROM_LOAD( "momoko07.bin", 0x18000, 0x8000, CRC(b94b38db) SHA1(9c9e45bbeca7b6b8b0051b144fb31fceaf5d6906) )
+	ROM_LOAD( "momoko04.r8", 0x0000,  0x8000, CRC(3ab3c2c3) SHA1(d4a0d7f83bf64769e90a2c264c6114ac308cb8b5) )
+	ROM_LOAD( "momoko05.p8", 0x8000,  0x8000, CRC(757cdd2b) SHA1(3471b42dc6458a18894dbd0638f4fe43c86dd70d) )
+	ROM_LOAD( "momoko06.n8", 0x10000, 0x8000, CRC(20cacf8b) SHA1(e2b39abfc960e1c472e2bcf0cf06825c39941c03) )
+	ROM_LOAD( "momoko07.l8", 0x18000, 0x8000, CRC(b94b38db) SHA1(9c9e45bbeca7b6b8b0051b144fb31fceaf5d6906) )
 
 	ROM_REGION( 0x2000, "user2", 0 ) /* BG color/priority table */
-	ROM_LOAD( "momoko08.bin", 0x0000,  0x2000, CRC(69b41702) SHA1(21b33b243dd6eaec8d41d9fd4d9e7faf2bd7f4d2) )
+	ROM_LOAD( "momoko08.h8", 0x0000,  0x2000, CRC(69b41702) SHA1(21b33b243dd6eaec8d41d9fd4d9e7faf2bd7f4d2) )
 
 	ROM_REGION( 0x4000, "user3", 0 ) /* FG map */
-	ROM_LOAD( "momoko15.bin", 0x0000,  0x4000, CRC(8028f806) SHA1(c7450d48803082f64af67fe752b6f49b71b6ff48) )
+	ROM_LOAD( "momoko15.k2", 0x0000,  0x4000, CRC(8028f806) SHA1(c7450d48803082f64af67fe752b6f49b71b6ff48) ) // On the FP-8631 PCB
 
 	ROM_REGION( 0x0120, "proms", 0 ) /* TEXT color */
 	ROM_LOAD( "momoko-c.bin", 0x0000,  0x0100, CRC(f35ccae0) SHA1(60b99dd3c96637dacba7e96a143b1a2d6ffd28b9) )
 	ROM_LOAD( "momoko-b.bin", 0x0100,  0x0020, CRC(427b0e5c) SHA1(aa2797b899571527cc96013fd3420b841954ee67) )
 ROM_END
 
-GAME( 1986, momoko, 0, momoko, momoko, driver_device, 0, ROT0, "Jaleco", "Momoko 120%", MACHINE_SUPPORTS_SAVE )
+ROM_START( momokoe )
+	ROM_REGION( 0x10000, "maincpu", 0 ) /* main CPU */
+	ROM_LOAD( "3.m6", 0x0000,  0x8000, CRC(84053a7d) SHA1(6e8fb22bb48954f4fed2530991ebe5b872c9c089) ) // age progression text in English
+	ROM_LOAD( "2.m5", 0x8000,  0x4000, CRC(98ad397b) SHA1(b7ae218d0d397b1e258ec6d1f836cb998f984092) )
+
+	ROM_REGION( 0x10000, "audiocpu", 0 ) /* sound CPU */
+	ROM_LOAD( "momoko01.u4", 0x0000,  0x8000, CRC(e8a6673c) SHA1(f8984b063929305c9058801202405e6d45254b5b) )
+
+	ROM_REGION( 0x2000, "gfx1", 0 ) /* text */
+	ROM_LOAD( "momoko13.u4", 0x0000,  0x2000, CRC(2745cf5a) SHA1(3db7c6319cac63df1620ef25508c5c45eaa4b141) ) // On the FP-8631 PCB
+
+	ROM_REGION( 0x2000, "gfx3", 0 ) /* FG */
+	ROM_LOAD( "momoko14.p2", 0x0000,  0x2000, CRC(cfccca05) SHA1(4ecff488a37ac76ecb9ecf8980bea30dcc9c9951) )
+
+	ROM_REGION( 0x10000, "gfx4", 0 ) /* sprite */
+	ROM_LOAD16_BYTE( "momoko16.e5", 0x0000,  0x8000, CRC(fc6876fc) SHA1(b2d06bc01ef9f4db9bf8902d67f31ccbb0fea61a) ) // On the FP-8631 PCB
+	ROM_LOAD16_BYTE( "momoko17.e6", 0x0001,  0x8000, CRC(45dc0247) SHA1(1b2bd4197ab7d237966e037c249b5bd623646c0b) ) // On the FP-8631 PCB
+
+	ROM_REGION( 0x20000, "gfx2", 0 ) /* BG */
+	ROM_LOAD16_BYTE( "momoko09.e8", 0x00000, 0x8000, CRC(9f5847c7) SHA1(6bc9a00622d8a23446294a8d5d467375c5719125) )
+	ROM_LOAD16_BYTE( "momoko11.c8", 0x00001, 0x8000, CRC(9c9fbd43) SHA1(7adfd7ea3dd6745c14e719883f1a86e0a3b3c0ff) )
+	ROM_LOAD16_BYTE( "momoko10.d8", 0x10000, 0x8000, CRC(ae17e74b) SHA1(f52657ea6b6ac518b70fd7b811d9699da27f67d9) )
+	ROM_LOAD16_BYTE( "momoko12.a8", 0x10001, 0x8000, CRC(1e29c9c4) SHA1(d78f102cefc9852b529dd317a76c7003ec2ad3d5) )
+
+	ROM_REGION( 0x20000, "user1", 0 ) /* BG map */
+	ROM_LOAD( "momoko04.r8", 0x0000,  0x8000, CRC(3ab3c2c3) SHA1(d4a0d7f83bf64769e90a2c264c6114ac308cb8b5) )
+	ROM_LOAD( "momoko05.p8", 0x8000,  0x8000, CRC(757cdd2b) SHA1(3471b42dc6458a18894dbd0638f4fe43c86dd70d) )
+	ROM_LOAD( "momoko06.n8", 0x10000, 0x8000, CRC(20cacf8b) SHA1(e2b39abfc960e1c472e2bcf0cf06825c39941c03) )
+	ROM_LOAD( "momoko07.l8", 0x18000, 0x8000, CRC(b94b38db) SHA1(9c9e45bbeca7b6b8b0051b144fb31fceaf5d6906) )
+
+	ROM_REGION( 0x2000, "user2", 0 ) /* BG color/priority table */
+	ROM_LOAD( "momoko08.h8", 0x0000,  0x2000, CRC(69b41702) SHA1(21b33b243dd6eaec8d41d9fd4d9e7faf2bd7f4d2) )
+
+	ROM_REGION( 0x4000, "user3", 0 ) /* FG map */
+	ROM_LOAD( "momoko15.k2", 0x0000,  0x4000, CRC(8028f806) SHA1(c7450d48803082f64af67fe752b6f49b71b6ff48) ) // On the FP-8631 PCB
+
+	ROM_REGION( 0x0120, "proms", 0 ) /* TEXT color */
+	ROM_LOAD( "momoko-c.bin", 0x0000,  0x0100, CRC(f35ccae0) SHA1(60b99dd3c96637dacba7e96a143b1a2d6ffd28b9) )
+	ROM_LOAD( "momoko-b.bin", 0x0100,  0x0020, CRC(427b0e5c) SHA1(aa2797b899571527cc96013fd3420b841954ee67) )
+ROM_END
+
+GAME( 1986, momoko,       0, momoko, momoko, driver_device, 0, ROT0, "Jaleco", "Momoko 120% (Japanese text)", MACHINE_SUPPORTS_SAVE )
+GAME( 1986, momokoe, momoko, momoko, momoko, driver_device, 0, ROT0, "Jaleco", "Momoko 120% (English text)",  MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/drivers/mpu3.cpp b/src/mame/drivers/mpu3.cpp
index 774f8b1..f914909 100644
--- a/src/mame/drivers/mpu3.cpp
+++ b/src/mame/drivers/mpu3.cpp
@@ -857,8 +857,7 @@ static MACHINE_CONFIG_START( mpu3base, mpu3_state )
 	MCFG_TIMER_DRIVER_ADD_PERIODIC("555_ic10", mpu3_state, ic10_callback, PERIOD_OF_555_ASTABLE(10000,1000,0.0000001))
 
 	/* 6840 PTM */
-	MCFG_DEVICE_ADD("ptm_ic2", PTM6840, 0)
-	MCFG_PTM6840_INTERNAL_CLOCK(MPU3_MASTER_CLOCK)
+	MCFG_DEVICE_ADD("ptm_ic2", PTM6840, MPU3_MASTER_CLOCK)
 	MCFG_PTM6840_EXTERNAL_CLOCKS(0, 0, 0)
 	MCFG_PTM6840_OUT0_CB(WRITELINE(mpu3_state, ic2_o1_callback))
 	MCFG_PTM6840_OUT1_CB(WRITELINE(mpu3_state, ic2_o2_callback))
diff --git a/src/mame/drivers/mpu4.cpp b/src/mame/drivers/mpu4.cpp
index 69cf56f..ebda900 100644
--- a/src/mame/drivers/mpu4.cpp
+++ b/src/mame/drivers/mpu4.cpp
@@ -3002,8 +3002,7 @@ MACHINE_CONFIG_FRAGMENT( mpu4_common )
 
 	MCFG_MSC1937_ADD("vfd",0)
 	/* 6840 PTM */
-	MCFG_DEVICE_ADD("ptm_ic2", PTM6840, 0)
-	MCFG_PTM6840_INTERNAL_CLOCK(MPU4_MASTER_CLOCK / 4)
+	MCFG_DEVICE_ADD("ptm_ic2", PTM6840, MPU4_MASTER_CLOCK / 4)
 	MCFG_PTM6840_EXTERNAL_CLOCKS(0, 0, 0)
 	MCFG_PTM6840_OUT0_CB(WRITELINE(mpu4_state, ic2_o1_callback))
 	MCFG_PTM6840_OUT1_CB(WRITELINE(mpu4_state, ic2_o2_callback))
@@ -3068,8 +3067,7 @@ MACHINE_CONFIG_FRAGMENT( mpu4_common )
 MACHINE_CONFIG_END
 
 MACHINE_CONFIG_FRAGMENT( mpu4_common2 )
-	MCFG_DEVICE_ADD("ptm_ic3ss", PTM6840, 0)
-	MCFG_PTM6840_INTERNAL_CLOCK(MPU4_MASTER_CLOCK / 4)
+	MCFG_DEVICE_ADD("ptm_ic3ss", PTM6840, MPU4_MASTER_CLOCK / 4)
 	MCFG_PTM6840_EXTERNAL_CLOCKS(0, 0, 0)
 	MCFG_PTM6840_OUT0_CB(DEVWRITELINE("ptm_ic3ss", ptm6840_device, set_c2))
 	MCFG_PTM6840_OUT1_CB(DEVWRITELINE("ptm_ic3ss", ptm6840_device, set_c1))
diff --git a/src/mame/drivers/mpu4vid.cpp b/src/mame/drivers/mpu4vid.cpp
index 1d69eb0..09ea564 100644
--- a/src/mame/drivers/mpu4vid.cpp
+++ b/src/mame/drivers/mpu4vid.cpp
@@ -189,23 +189,15 @@ TODO:
 #include "machine/roc10937.h"
 #include "machine/meters.h"
 #include "video/scn2674.h"
-
+#include "video/ef9369.h"
 #include "cpu/m68000/m68000.h"
 #include "machine/6850acia.h"
 #include "sound/saa1099.h"
-#include "machine/nvram.h"
 #include "crmaze2p.lh"
 #include "crmaze4p.lh"
 #include "includes/mpu4.h"
-#include "cpu/m68000/m68000.h"
 
 
-struct ef9369_t
-{
-	uint32_t addr;
-	uint16_t clut[16];    /* 13-bits - a marking bit and a 444 color */
-};
-
 struct bt471_t
 {
 	uint8_t address;
@@ -245,7 +237,6 @@ public:
 	optional_ioport m_tracky_port;
 	required_device<gfxdecode_device> m_gfxdecode;
 
-	struct ef9369_t m_pal;
 	struct bt471_t m_bt471;
 
 	//Video
@@ -291,8 +282,7 @@ public:
 	DECLARE_WRITE_LINE_MEMBER(update_mpu68_interrupts);
 	DECLARE_READ16_MEMBER( mpu4_vid_vidram_r );
 	DECLARE_WRITE16_MEMBER( mpu4_vid_vidram_w );
-	DECLARE_WRITE8_MEMBER( ef9369_w );
-	DECLARE_READ8_MEMBER( ef9369_r );
+	EF9369_COLOR_UPDATE(ef9369_color_update);
 	DECLARE_WRITE8_MEMBER( bt471_w );
 	DECLARE_READ8_MEMBER( bt471_r );
 	DECLARE_WRITE8_MEMBER( vidcharacteriser_w );
@@ -444,76 +434,9 @@ VIDEO_START_MEMBER(mpu4vid_state,mpu4_vid)
 	m_gfxdecode->set_gfx(m_gfx_index+0, std::make_unique<gfx_element>(*m_palette, mpu4_vid_char_8x8_layout, reinterpret_cast<uint8_t *>(m_vid_vidram.target()), NATIVE_ENDIAN_VALUE_LE_BE(8,0), m_palette->entries() / 16, 0));
 }
 
-
-
-
-/****************************
- *  EF9369 color palette IC
- *  (16 colors from 4096)
- ****************************/
-
-/* Non-multiplexed mode */
-
-WRITE8_MEMBER(mpu4vid_state::ef9369_w )
-{
-	struct ef9369_t &pal = m_pal;
-
-	/* Address register */
-	if (offset & 1)
-	{
-		pal.addr = data & 0x1f;
-	}
-	/* Data register */
-	else
-	{
-		uint32_t entry = pal.addr >> 1;
-
-		if ((pal.addr & 1) == 0)
-		{
-			pal.clut[entry] &= ~0x00ff;
-			pal.clut[entry] |= data;
-		}
-		else
-		{
-			uint16_t col;
-
-			pal.clut[entry] &= ~0x1f00;
-			pal.clut[entry] |= (data & 0x1f) << 8;
-
-			/* Remove the marking bit */
-			col = pal.clut[entry] & 0xfff;
-
-			/* Update the MAME palette */
-			m_palette->set_pen_color(entry, pal4bit(col >> 8), pal4bit(col >> 4), pal4bit(col >> 0));
-		}
-
-			/* Address register auto-increment */
-		if (++pal.addr == 32)
-			pal.addr = 0;
-	}
-}
-
-
-READ8_MEMBER(mpu4vid_state::ef9369_r )
+EF9369_COLOR_UPDATE( mpu4vid_state::ef9369_color_update )
 {
-	struct ef9369_t &pal = m_pal;
-	if ((offset & 1) == 0)
-	{
-		uint16_t col = pal.clut[pal.addr >> 1];
-
-/*      if ((pal.addr & 1) == 0)
-            return col & 0xff;
-        else
-            return col >> 8;
-            */
-
-	return col;
-	}
-	else
-	{
-		/* Address register is write only */
-		return 0xff;
-	}
+	m_palette->set_pen_color(entry, pal4bit(cc), pal4bit(cb), pal4bit(ca));
 }
 
 /******************************************
@@ -1246,12 +1169,10 @@ static ADDRESS_MAP_START( mpu4_68k_map, AS_PROGRAM, 16, mpu4vid_state )
 //  AM_RANGE(0x810000, 0x81ffff) AM_RAM /* ? */
 	AM_RANGE(0x900000, 0x900001) AM_DEVWRITE8("saa", saa1099_device, data_w, 0x00ff)
 	AM_RANGE(0x900002, 0x900003) AM_DEVWRITE8("saa", saa1099_device, control_w, 0x00ff)
-	AM_RANGE(0xa00000, 0xa00003) AM_READWRITE8(ef9369_r, ef9369_w,0x00ff)
+	AM_RANGE(0xa00000, 0xa00001) AM_DEVREADWRITE8("ef9369", ef9369_device, data_r, data_w, 0x00ff)
+	AM_RANGE(0xa00002, 0xa00003) AM_DEVWRITE8("ef9369", ef9369_device, address_w, 0x00ff)
 /*  AM_RANGE(0xa00004, 0xa0000f) AM_READWRITE(mpu4_vid_unmap_r, mpu4_vid_unmap_w) */
-
-
 	AM_RANGE(0xb00000, 0xb0000f) AM_DEVREADWRITE8("scn2674_vid", scn2674_device, read, write,0x00ff)
-
 	AM_RANGE(0xc00000, 0xc1ffff) AM_READWRITE(mpu4_vid_vidram_r, mpu4_vid_vidram_w) AM_SHARE("vid_vidram")
 	AM_RANGE(0xff8000, 0xff8001) AM_DEVREADWRITE8("acia6850_1", acia6850_device, status_r, control_w, 0x00ff)
 	AM_RANGE(0xff8002, 0xff8003) AM_DEVREADWRITE8("acia6850_1", acia6850_device, data_r, data_w, 0x00ff)
@@ -1266,10 +1187,9 @@ static ADDRESS_MAP_START( mpu4oki_68k_map, AS_PROGRAM, 16, mpu4vid_state )
 	AM_RANGE(0x800000, 0x80ffff) AM_RAM AM_SHARE("vid_mainram")
 	AM_RANGE(0x900000, 0x900001) AM_DEVWRITE8("saa", saa1099_device, data_w, 0x00ff)
 	AM_RANGE(0x900002, 0x900003) AM_DEVWRITE8("saa", saa1099_device, control_w, 0x00ff)
-	AM_RANGE(0xa00000, 0xa00003) AM_READWRITE8(ef9369_r, ef9369_w,0x00ff)
-
+	AM_RANGE(0xa00000, 0xa00001) AM_DEVREADWRITE8("ef9369", ef9369_device, data_r, data_w, 0x00ff)
+	AM_RANGE(0xa00002, 0xa00003) AM_DEVWRITE8("ef9369", ef9369_device, address_w, 0x00ff)
 	AM_RANGE(0xb00000, 0xb0000f) AM_DEVREADWRITE8("scn2674_vid", scn2674_device, read, write,0x00ff)
-
 	AM_RANGE(0xc00000, 0xc1ffff) AM_READWRITE(mpu4_vid_vidram_r, mpu4_vid_vidram_w) AM_SHARE("vid_vidram")
 	AM_RANGE(0xff8000, 0xff8001) AM_DEVREADWRITE8("acia6850_1", acia6850_device, status_r, control_w, 0x00ff)
 	AM_RANGE(0xff8002, 0xff8003) AM_DEVREADWRITE8("acia6850_1", acia6850_device, data_r, data_w, 0x00ff)
@@ -1281,17 +1201,16 @@ static ADDRESS_MAP_START( mpu4oki_68k_map, AS_PROGRAM, 16, mpu4vid_state )
 //  AM_RANGE(0xfff000, 0xffffff) AM_NOP /* Possible bug, reads and writes here */
 ADDRESS_MAP_END
 
-
 static ADDRESS_MAP_START( bwbvid_68k_map, AS_PROGRAM, 16, mpu4vid_state )
 	AM_RANGE(0x000000, 0x7fffff) AM_ROM
 	AM_RANGE(0x800000, 0x80ffff) AM_RAM AM_SHARE("vid_mainram")
 	AM_RANGE(0x810000, 0x81ffff) AM_RAM /* ? */
 	AM_RANGE(0x900000, 0x900001) AM_DEVWRITE8("saa", saa1099_device, data_w, 0x00ff)
 	AM_RANGE(0x900002, 0x900003) AM_DEVWRITE8("saa", saa1099_device, control_w, 0x00ff)
-	AM_RANGE(0xa00000, 0xa00003) AM_READWRITE8(ef9369_r, ef9369_w,0x00ff)
+	AM_RANGE(0xa00000, 0xa00001) AM_DEVREADWRITE8("ef9369", ef9369_device, data_r, data_w, 0x00ff)
+	AM_RANGE(0xa00002, 0xa00003) AM_DEVWRITE8("ef9369", ef9369_device, address_w, 0x00ff)
 //  AM_RANGE(0xa00000, 0xa0000f) AM_READWRITE(bt471_r,bt471_w) //Some games use this
 /*  AM_RANGE(0xa00004, 0xa0000f) AM_READWRITE(mpu4_vid_unmap_r, mpu4_vid_unmap_w) */
-
 	AM_RANGE(0xb00000, 0xb0000f) AM_DEVREADWRITE8("scn2674_vid", scn2674_device, read, write,0x00ff)
 	AM_RANGE(0xc00000, 0xc1ffff) AM_READWRITE(mpu4_vid_vidram_r, mpu4_vid_vidram_w) AM_SHARE("vid_vidram")
 	AM_RANGE(0xe00000, 0xe00001) AM_DEVREADWRITE8("acia6850_1", acia6850_device, status_r, control_w, 0x00ff)
@@ -1306,10 +1225,10 @@ static ADDRESS_MAP_START( bwbvid5_68k_map, AS_PROGRAM, 16, mpu4vid_state )
 	AM_RANGE(0x810000, 0x81ffff) AM_RAM /* ? */
 	AM_RANGE(0x900000, 0x900001) AM_DEVWRITE8("saa", saa1099_device, data_w, 0x00ff)
 	AM_RANGE(0x900002, 0x900003) AM_DEVWRITE8("saa", saa1099_device, control_w, 0x00ff)
-	AM_RANGE(0xa00000, 0xa00003) AM_READWRITE8(ef9369_r, ef9369_w,0x00ff)
+	AM_RANGE(0xa00000, 0xa00001) AM_DEVREADWRITE8("ef9369", ef9369_device, data_r, data_w, 0x00ff)
+	AM_RANGE(0xa00002, 0xa00003) AM_DEVWRITE8("ef9369", ef9369_device, address_w, 0x00ff)
 	//AM_RANGE(0xa00000, 0xa00003) AM_READWRITE8(bt471_r,bt471_w,0x00ff) Some games use this
 /*  AM_RANGE(0xa00004, 0xa0000f) AM_READWRITE(mpu4_vid_unmap_r, mpu4_vid_unmap_w) */
-
 	AM_RANGE(0xb00000, 0xb0000f) AM_DEVREADWRITE8("scn2674_vid", scn2674_device, read, write,0x00ff)
 	AM_RANGE(0xc00000, 0xc1ffff) AM_READWRITE(mpu4_vid_vidram_r, mpu4_vid_vidram_w) AM_SHARE("vid_vidram")
 	AM_RANGE(0xe00000, 0xe00001) AM_DEVREADWRITE8("acia6850_1", acia6850_device, status_r, control_w, 0x00ff)
@@ -1321,8 +1240,6 @@ static ADDRESS_MAP_START( bwbvid5_68k_map, AS_PROGRAM, 16, mpu4vid_state )
 	AM_RANGE(0xe04000, 0xe0400f) AM_READWRITE8(bwb_characteriser_r, bwb_characteriser_w, 0x00ff)//AM_READWRITE(adpcm_r, adpcm_w)  CHR ?
 ADDRESS_MAP_END
 
-
-
 /* TODO: Fix up MPU4 map*/
 static ADDRESS_MAP_START( mpu4_6809_map, AS_PROGRAM, 8, mpu4_state )
 	AM_RANGE(0x0000, 0x07ff) AM_RAM AM_SHARE("nvram")
@@ -1343,7 +1260,6 @@ ADDRESS_MAP_END
 
 
 
-
 static MACHINE_CONFIG_START( mpu4_vid, mpu4vid_state )
 	MCFG_CPU_ADD("maincpu", M6809, MPU4_MASTER_CLOCK/4 )
 	MCFG_CPU_PROGRAM_MAP(mpu4_6809_map)
@@ -1378,10 +1294,12 @@ static MACHINE_CONFIG_START( mpu4_vid, mpu4vid_state )
 	MCFG_MACHINE_RESET_OVERRIDE(mpu4vid_state,mpu4_vid)
 	MCFG_VIDEO_START_OVERRIDE (mpu4vid_state,mpu4_vid)
 
-	MCFG_PALETTE_ADD("palette", 16)
+	MCFG_PALETTE_ADD("palette", ef9369_device::NUMCOLORS)
+
+	MCFG_EF9369_ADD("ef9369")
+	MCFG_EF9369_COLOR_UPDATE_CB(mpu4vid_state, ef9369_color_update)
 
-	MCFG_DEVICE_ADD("6840ptm_68k", PTM6840, 0)
-	MCFG_PTM6840_INTERNAL_CLOCK(VIDEO_MASTER_CLOCK / 10) /* 68k E clock */
+	MCFG_DEVICE_ADD("6840ptm_68k", PTM6840, VIDEO_MASTER_CLOCK / 10) /* 68k E clock */
 	MCFG_PTM6840_EXTERNAL_CLOCKS(0, 0, 0)
 	MCFG_PTM6840_OUT0_CB(WRITELINE(mpu4vid_state, vid_o1_callback))
 	MCFG_PTM6840_OUT1_CB(WRITELINE(mpu4vid_state, vid_o2_callback))
diff --git a/src/mame/drivers/mustache.cpp b/src/mame/drivers/mustache.cpp
index 1400753..0080e6d 100644
--- a/src/mame/drivers/mustache.cpp
+++ b/src/mame/drivers/mustache.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /***************************************************************************
 
@@ -92,25 +92,25 @@ static INPUT_PORTS_START( mustache )
 	PORT_BIT( 0xf9, IP_ACTIVE_LOW, IPT_UNUSED  )
 
 	PORT_START("DSWA")
-	PORT_DIPNAME( 0x01, 0x01, DEF_STR( Cabinet ) ) PORT_DIPLOCATION("SW 2:!1")
+	PORT_DIPNAME( 0x01, 0x01, DEF_STR( Cabinet ) ) PORT_DIPLOCATION("SW 2:1")
 	PORT_DIPSETTING(    0x01, DEF_STR( Upright ) )
 	PORT_DIPSETTING(    0x00, DEF_STR( Cocktail ) )
-	PORT_DIPNAME( 0x06, 0x04, DEF_STR( Difficulty ) ) PORT_DIPLOCATION("SW 2:!2,!3")
+	PORT_DIPNAME( 0x06, 0x04, DEF_STR( Difficulty ) ) PORT_DIPLOCATION("SW 2:2,3")
 	PORT_DIPSETTING(    0x06, DEF_STR( Easy ) )
 	PORT_DIPSETTING(    0x04, DEF_STR( Normal ) )
 	PORT_DIPSETTING(    0x02, DEF_STR( Hard ) )
 	PORT_DIPSETTING(    0x00, DEF_STR( Hardest ) )
-	PORT_DIPNAME( 0x18, 0x18, DEF_STR( Lives ) ) PORT_DIPLOCATION("SW 2:!4,!5")
+	PORT_DIPNAME( 0x18, 0x18, DEF_STR( Lives ) ) PORT_DIPLOCATION("SW 2:4,5")
 	PORT_DIPSETTING(    0x10, "1" )
 	PORT_DIPSETTING(    0x18, "3" )
 	PORT_DIPSETTING(    0x08, "4" )
 	PORT_DIPSETTING(    0x00, "5" )
-	PORT_DIPNAME( 0x20, 0x00, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SW 2:!6")
+	PORT_DIPNAME( 0x20, 0x00, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SW 2:6")
 	PORT_DIPSETTING(    0x20, DEF_STR( Off ) )
 	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
 
 	PORT_START("DSWB")
-	PORT_DIPNAME( 0x07, 0x07, DEF_STR( Coin_A ) ) PORT_DIPLOCATION("SW 1:!1,!2,!3")
+	PORT_DIPNAME( 0x07, 0x07, DEF_STR( Coin_A ) ) PORT_DIPLOCATION("SW 1:1,2,3")
 	PORT_DIPSETTING(    0x00, DEF_STR( 5C_1C ) )
 	PORT_DIPSETTING(    0x04, DEF_STR( 4C_1C ) )
 	PORT_DIPSETTING(    0x02, DEF_STR( 3C_1C ) )
@@ -119,16 +119,18 @@ static INPUT_PORTS_START( mustache )
 	PORT_DIPSETTING(    0x03, DEF_STR( 1C_2C ) )
 	PORT_DIPSETTING(    0x05, DEF_STR( 1C_3C ) )
 	PORT_DIPSETTING(    0x01, DEF_STR( 1C_5C ) )
-	PORT_DIPNAME( 0x18, 0x18, DEF_STR( Coin_B ) ) PORT_DIPLOCATION("SW 1:!4,!5")
+	PORT_DIPNAME( 0x18, 0x18, DEF_STR( Coin_B ) ) PORT_DIPLOCATION("SW 1:4,5")
 	PORT_DIPSETTING(    0x10, DEF_STR( 2C_1C ) )
 	PORT_DIPSETTING(    0x18, DEF_STR( 1C_1C ) )
 	PORT_DIPSETTING(    0x00, DEF_STR( 2C_3C ) )
 	PORT_DIPSETTING(    0x08, DEF_STR( 1C_2C ) )
-	PORT_SERVICE( 0x20, IP_ACTIVE_LOW ) PORT_DIPLOCATION("SW 1:!6")
-	PORT_DIPNAME( 0x40, 0x40, DEF_STR( Free_Play ) ) PORT_DIPLOCATION("SW 1:!7")
+	PORT_SERVICE( 0x20, IP_ACTIVE_LOW ) PORT_DIPLOCATION("SW 1:6")
+	PORT_DIPNAME( 0x40, 0x40, DEF_STR( Free_Play ) ) PORT_DIPLOCATION("SW 1:7")
 	PORT_DIPSETTING(    0x40, DEF_STR( Off ) )
 	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
-// There is an 8th dipswitch here, which controls screen flip, but the operator sheet implies it does it via hardware, i.e. not readable by cpu. May need further investigation.
+	PORT_DIPNAME( 0x80, 0x80, DEF_STR( Flip_Screen ) ) PORT_DIPLOCATION("SW 1:8")
+	PORT_DIPSETTING(    0x80, DEF_STR( Off ) )
+	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
 
 INPUT_PORTS_END
 
diff --git a/src/mame/drivers/namcos12.cpp b/src/mame/drivers/namcos12.cpp
index 3e847b5..747ee95 100644
--- a/src/mame/drivers/namcos12.cpp
+++ b/src/mame/drivers/namcos12.cpp
@@ -1688,13 +1688,10 @@ static MACHINE_CONFIG_START( coh700, namcos12_state )
 	MCFG_RTC4543_ADD("rtc", XTAL_32_768kHz)
 	MCFG_RTC4543_DATA_CALLBACK(DEVWRITELINE("sub:sci1", h8_sci_device, rx_w))
 
-	MCFG_LINE_DISPATCH_ADD("clk_dispatch", 2)
-	MCFG_LINE_DISPATCH_FWD_CB(0, 2, DEVWRITELINE(":rtc", rtc4543_device, clk_w)) MCFG_DEVCB_INVERT
-	MCFG_LINE_DISPATCH_FWD_CB(1, 2, DEVWRITELINE(":namco_settings", namco_settings_device, clk_w))
-
 	MCFG_DEVICE_MODIFY("sub:sci1")
 	MCFG_H8_SCI_TX_CALLBACK(DEVWRITELINE(":namco_settings", namco_settings_device, data_w))
-	MCFG_H8_SCI_CLK_CALLBACK(DEVWRITELINE(":clk_dispatch", devcb_line_dispatch_device<2>, in_w))
+	MCFG_H8_SCI_CLK_CALLBACK(DEVWRITELINE(":rtc", rtc4543_device, clk_w)) MCFG_DEVCB_INVERT
+	MCFG_DEVCB_CHAIN_OUTPUT(DEVWRITELINE(":namco_settings", namco_settings_device, clk_w))
 
 	MCFG_AT28C16_ADD("at28c16", nullptr)
 
diff --git a/src/mame/drivers/namcos23.cpp b/src/mame/drivers/namcos23.cpp
index 133193d..b79ac26 100644
--- a/src/mame/drivers/namcos23.cpp
+++ b/src/mame/drivers/namcos23.cpp
@@ -3566,13 +3566,10 @@ static MACHINE_CONFIG_START( gorgon, namcos23_state )
 	MCFG_RTC4543_ADD("rtc", XTAL_32_768kHz)
 	MCFG_RTC4543_DATA_CALLBACK(DEVWRITELINE("subcpu:sci1", h8_sci_device, rx_w))
 
-	MCFG_LINE_DISPATCH_ADD("clk_dispatch", 2)
-	MCFG_LINE_DISPATCH_FWD_CB(0, 2, DEVWRITELINE(":rtc", rtc4543_device, clk_w)) MCFG_DEVCB_INVERT
-	MCFG_LINE_DISPATCH_FWD_CB(1, 2, DEVWRITELINE(":namco_settings", namco_settings_device, clk_w))
-
 	MCFG_DEVICE_MODIFY("subcpu:sci1")
 	MCFG_H8_SCI_TX_CALLBACK(DEVWRITELINE(":namco_settings", namco_settings_device, data_w))
-	MCFG_H8_SCI_CLK_CALLBACK(DEVWRITELINE(":clk_dispatch", devcb_line_dispatch_device<2>, in_w))
+	MCFG_H8_SCI_CLK_CALLBACK(DEVWRITELINE(":rtc", rtc4543_device, clk_w)) MCFG_DEVCB_INVERT
+	MCFG_DEVCB_CHAIN_OUTPUT(DEVWRITELINE(":namco_settings", namco_settings_device, clk_w))
 
 	MCFG_NVRAM_ADD_0FILL("nvram")
 
@@ -3635,13 +3632,10 @@ static MACHINE_CONFIG_START( s23, namcos23_state )
 	MCFG_RTC4543_ADD("rtc", XTAL_32_768kHz)
 	MCFG_RTC4543_DATA_CALLBACK(DEVWRITELINE("subcpu:sci1", h8_sci_device, rx_w))
 
-	MCFG_LINE_DISPATCH_ADD("clk_dispatch", 2)
-	MCFG_LINE_DISPATCH_FWD_CB(0, 2, DEVWRITELINE(":rtc", rtc4543_device, clk_w)) MCFG_DEVCB_INVERT
-	MCFG_LINE_DISPATCH_FWD_CB(1, 2, DEVWRITELINE(":namco_settings", namco_settings_device, clk_w))
-
 	MCFG_DEVICE_MODIFY("subcpu:sci1")
 	MCFG_H8_SCI_TX_CALLBACK(DEVWRITELINE(":namco_settings", namco_settings_device, data_w))
-	MCFG_H8_SCI_CLK_CALLBACK(DEVWRITELINE(":clk_dispatch", devcb_line_dispatch_device<2>, in_w))
+	MCFG_H8_SCI_CLK_CALLBACK(DEVWRITELINE(":rtc", rtc4543_device, clk_w)) MCFG_DEVCB_INVERT
+	MCFG_DEVCB_CHAIN_OUTPUT(DEVWRITELINE(":namco_settings", namco_settings_device, clk_w))
 
 	MCFG_NVRAM_ADD_0FILL("nvram")
 
@@ -3715,13 +3709,10 @@ static MACHINE_CONFIG_START( ss23, namcos23_state )
 	MCFG_RTC4543_ADD("rtc", XTAL_32_768kHz)
 	MCFG_RTC4543_DATA_CALLBACK(DEVWRITELINE("subcpu:sci1", h8_sci_device, rx_w))
 
-	MCFG_LINE_DISPATCH_ADD("clk_dispatch", 2)
-	MCFG_LINE_DISPATCH_FWD_CB(0, 2, DEVWRITELINE(":rtc", rtc4543_device, clk_w)) MCFG_DEVCB_INVERT
-	MCFG_LINE_DISPATCH_FWD_CB(1, 2, DEVWRITELINE(":namco_settings", namco_settings_device, clk_w))
-
 	MCFG_DEVICE_MODIFY("subcpu:sci1")
 	MCFG_H8_SCI_TX_CALLBACK(DEVWRITELINE(":namco_settings", namco_settings_device, data_w))
-	MCFG_H8_SCI_CLK_CALLBACK(DEVWRITELINE(":clk_dispatch", devcb_line_dispatch_device<2>, in_w))
+	MCFG_H8_SCI_CLK_CALLBACK(DEVWRITELINE(":rtc", rtc4543_device, clk_w)) MCFG_DEVCB_INVERT
+	MCFG_DEVCB_CHAIN_OUTPUT(DEVWRITELINE(":namco_settings", namco_settings_device, clk_w))
 
 	MCFG_NVRAM_ADD_0FILL("nvram")
 
diff --git a/src/mame/drivers/naomi.cpp b/src/mame/drivers/naomi.cpp
index 82ad769..0bf4221 100644
--- a/src/mame/drivers/naomi.cpp
+++ b/src/mame/drivers/naomi.cpp
@@ -402,8 +402,8 @@ Guilty Gear X                                   841-0013C    23356   14 (64Mb)
 Gun Spike                                       841-0012C    23210   12 (64Mb)   present     315-6213  317-5060-COM   \same ROM board
 Cannon Spike                                    841-0012C-01 23210   12 (64Mb)   present     315-6213  317-5060-COM   /
 Heavy Metal Geomatrix (Rev B)                   HMG016007    23716A  11 (64Mb)   present     315-6213  317-5071-COM   joystick + 2 buttons
-House of the Dead 2                             834-13636    21385   20 (64Mb)   not present 315-6213  not present
-House of the Dead 2 (USA)                       834-13636    21585   20 (64Mb)   not present 315-6213  not present    PCB s/n is 834-13636-01
+House of the Dead 2                             834-13636    21385   20 (64Mb)   not present           not present    \ ROM board type is 837-13390
+House of the Dead 2 (USA)                       834-13636-01 21585   20 (64Mb)   not present           not present    / uses Lattice ispLSI 2032 80LJ instead of Xilinx
 Idol Janshi Suchie-Pai 3                        841-0002C    21979   14 (64Mb)   ?           315-6213  317-5047-JPN   requires mahjong panel
 Jambo! Safari (Rev A)                           840-0013C    22826A   8 (64Mb)   ?           315-6213  317-0264-COM
 Mars TV                                         840-0025C    22993   15 (64Mb)   present     315-6213  317-0274-JPN
@@ -594,7 +594,7 @@ Derby Owners Club II Ver.2.1 (Japan) (Rev B)    840-0083C  22306B  11 (128Mb)  3
 Derby Owners Club World Edition (Rev C)         840-0088C  22336C   7 (128Mb)  315-6319A  315-6213  not present   not present
 Derby Owners Club World Edition EX (Rev D)      840-0088C  22336D   7 (128Mb)  315-6319A  315-6213  not present   not present  2 MaskROM are different from Rev C
 Giga Wing 2                                     841-0014C  22270    5 (128Mb)  315-6319A  315-6213  317-5064-COM  ?
-Mobile Suit Gundam: Federation Vs. Zeon         841-0017C  23638   10 (128Mb)  315-6319A  315-6213  317-5070-COM  ?
+Mobile Suit Gundam: Federation Vs. Zeon         841-0017C  23638   10 (128Mb)  315-6319A  315-6213  317-5070-COM  not present
 Moero! Justice Gakuen / Project Justice (Rev A) 841-0015C  23548A  11 (128Mb)  315-6319A  315-6213  317-5065-COM  present
 MushiKing - The King Of Beetle 2K5 1ST          840-0158C  24286    7 (128Mb)  315-6319A  315-6213  not present   not present  requires 610-0669 barcode reader
 Oinori-daimyoujin Matsuri                       840-0126C  24053    5 (128Mb)  315-6319A  315-6213  not present   not present  requires 837-14274 "G2 EXPANSION BD" (similar to hopper 837-14381 but with ARC NET chip)
@@ -7705,8 +7705,8 @@ ROM_START( shaktam )
 	DISK_IMAGE_READONLY( "gds-0002b", 0, SHA1(c656497b44d5ca4743aa1a8d836af2bfa3484dd5) )
 
 	ROM_REGION( 0x4000, "pic", ROMREGION_ERASEFF)
-	// PIC label is unknown
-	ROM_LOAD("317-xxxx-com.pic", 0x00, 0x4000, CRC(9e1a8971) SHA1(022a1781b5d7346b61defe921dbabf11331834d7) )
+	// PIC number is guess
+	ROM_LOAD("317-0299-com.pic", 0x00, 0x4000, CRC(9e1a8971) SHA1(022a1781b5d7346b61defe921dbabf11331834d7) )
 ROM_END
 
 ROM_START( sprtjam )
diff --git a/src/mame/drivers/nbmj8688.cpp b/src/mame/drivers/nbmj8688.cpp
index 3d82f05..9ab21bb 100644
--- a/src/mame/drivers/nbmj8688.cpp
+++ b/src/mame/drivers/nbmj8688.cpp
@@ -545,25 +545,18 @@ static INPUT_PORTS_START( mjcamera )
 	PORT_DIPNAME( 0x10, 0x10, DEF_STR( Flip_Screen ) )      PORT_DIPLOCATION("DSWA:5")
 	PORT_DIPSETTING(    0x10, DEF_STR( Off ) )
 	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
-	PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) )          PORT_DIPLOCATION("DSWA:6")
+	PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unused ) )           PORT_DIPLOCATION("DSWA:6")
 	PORT_DIPSETTING(    0x20, DEF_STR( Off ) )
 	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
-	PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) )          PORT_DIPLOCATION("DSWA:7")
+	PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unused ) )           PORT_DIPLOCATION("DSWA:7")
 	PORT_DIPSETTING(    0x40, DEF_STR( Off ) )
 	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
 	PORT_DIPNAME( 0x80, 0x80, "Character Display Test" )    PORT_DIPLOCATION("DSWA:8")
 	PORT_DIPSETTING(    0x80, DEF_STR( Off ) )
 	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
 
-	PORT_START("DSWB")
-	PORT_DIPUNKNOWN_DIPLOC( 0x01, 0x01, "DSWB:1" )
-	PORT_DIPUNKNOWN_DIPLOC( 0x02, 0x02, "DSWB:2" )
-	PORT_DIPUNKNOWN_DIPLOC( 0x04, 0x04, "DSWB:3" )
-	PORT_DIPUNKNOWN_DIPLOC( 0x08, 0x08, "DSWB:4" )
-	PORT_DIPUNKNOWN_DIPLOC( 0x10, 0x10, "DSWB:5" )
-	PORT_DIPUNKNOWN_DIPLOC( 0x20, 0x20, "DSWB:6" )
-	PORT_DIPUNKNOWN_DIPLOC( 0x40, 0x40, "DSWB:7" )
-	PORT_DIPUNKNOWN_DIPLOC( 0x80, 0x80, "DSWB:8" )
+	PORT_START("DSWB") // Does not exist on PCB
+	PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
 
 	PORT_START("SYSTEM")
 	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, nbmj8688_state, nb1413m3_busyflag_r, nullptr)    // DRAW BUSY
diff --git a/src/mame/drivers/neodriv.hxx b/src/mame/drivers/neodriv.hxx
index 6a90987..777ece7 100644
--- a/src/mame/drivers/neodriv.hxx
+++ b/src/mame/drivers/neodriv.hxx
@@ -1149,28 +1149,28 @@ ROM_END
 
 ROM_START( burningfpa ) /* later prototype - Sx, Vx and Cx data all matches final game, but with different rom arranagement, Px & Mx unique */
 	ROM_REGION( 0x100000, "cslot1:maincpu", ROMREGION_BE|ROMREGION_16BIT )
-	ROM_LOAD16_BYTE( "018-p1.bin", 0x000001, 0x080000, CRC(f7d15752) SHA1(334b7e5c8e9099d39424e72db66846d0b9e534de) )
-	ROM_LOAD16_BYTE( "018-p2.bin", 0x000000, 0x080000, CRC(ffae22fb) SHA1(82f2f81fe96b3c6953985964e12e93e79410ab9e) )
+	ROM_LOAD16_BYTE( "018_p1_1f28.podd", 0x000001, 0x080000, CRC(f7d15752) SHA1(334b7e5c8e9099d39424e72db66846d0b9e534de) )
+	ROM_LOAD16_BYTE( "018_p2_3217.peven", 0x000000, 0x080000, CRC(ffae22fb) SHA1(82f2f81fe96b3c6953985964e12e93e79410ab9e) )
 
-	NEO_SFIX_128K( "018-s1.bin", CRC(6799ea0d) SHA1(ec75ef9dfdcb0b123574fc6d81ebaaadfba32fb5) )
+	NEO_SFIX_128K( "018_s1_4491.s1", CRC(6799ea0d) SHA1(ec75ef9dfdcb0b123574fc6d81ebaaadfba32fb5) )
 
-	NEO_BIOS_AUDIO_128K( "018-m1.bin", CRC(2b0c0415) SHA1(a5a0d5e3ea2ef77b6f5cd14f2907ab2f1aed76b7) )
+	NEO_BIOS_AUDIO_128K( "018_m1_d13e.m1", CRC(2b0c0415) SHA1(a5a0d5e3ea2ef77b6f5cd14f2907ab2f1aed76b7) )
 
 	ROM_REGION( 0x200000, "cslot1:ymsnd", 0 )
-	ROM_LOAD( "018-v11.bin", 0x000000, 0x080000, CRC(b55b9670) SHA1(b0ff38b2dca1361ad155e90be3674dbea1c0a53c) )
-	ROM_LOAD( "018-v12.bin", 0x080000, 0x080000, CRC(a0bcf260) SHA1(5d1f2613cf4a292557f37e6f44a90b20d11ed8cd) )
-	ROM_LOAD( "018-v13.bin", 0x100000, 0x080000, CRC(270f4707) SHA1(29e763acc9fd4b94d8b5d0ad917e20d8a66bbe49) )
-	ROM_LOAD( "018-v24.bin", 0x180000, 0x080000, CRC(924e3d69) SHA1(927091f9a098f00eb303f5567f4ee926bcb170e3) )
+	ROM_LOAD( "018_v11_6c00.v11", 0x000000, 0x080000, CRC(b55b9670) SHA1(b0ff38b2dca1361ad155e90be3674dbea1c0a53c) )
+	ROM_LOAD( "018_v12_8146.v12", 0x080000, 0x080000, CRC(a0bcf260) SHA1(5d1f2613cf4a292557f37e6f44a90b20d11ed8cd) )
+	ROM_LOAD( "018_v13_b813.v13", 0x100000, 0x080000, CRC(270f4707) SHA1(29e763acc9fd4b94d8b5d0ad917e20d8a66bbe49) )
+	ROM_LOAD( "018_v24_22ee.v24", 0x180000, 0x080000, CRC(924e3d69) SHA1(927091f9a098f00eb303f5567f4ee926bcb170e3) )
 
 	ROM_REGION( 0x400000, "cslot1:sprites", 0 ) // note, ROM_LOAD32_BYTE
-	ROM_LOAD32_BYTE( "018-c1.bin", 0x000000, 0x80000, CRC(3a441c6a) SHA1(0347d47a689af67426be42b4c99da101ee01ce11) ) /* Plane 0 */
-	ROM_LOAD32_BYTE( "018-c2.bin", 0x000002, 0x80000, CRC(bb72404b) SHA1(7620fccc50ecacf732bb1382abef42212d369f8c) ) /* Plane 2 */
-	ROM_LOAD32_BYTE( "018-c3.bin", 0x000001, 0x80000, CRC(87bffd2f) SHA1(0f7c835029a3f561861a1a07987dad23a32a899c) ) /* Plane 1 */
-	ROM_LOAD32_BYTE( "018-c4.bin", 0x000003, 0x80000, CRC(33803163) SHA1(888ba63618a2ca541883a612f0c75ffa96f1c528) ) /* Plane 3 */
-	ROM_LOAD32_BYTE( "018-c5.bin", 0x200000, 0x80000, CRC(74391952) SHA1(0f7451ff74901e7250214a7604a37add56ad7e1f) ) /* Plane 0 */
-	ROM_LOAD32_BYTE( "018-c6.bin", 0x200002, 0x80000, CRC(95e220e6) SHA1(cef4f7c697ab6d20e1b5c85df773d0f1a79e3008) ) /* Plane 2 */
-	ROM_LOAD32_BYTE( "018-c7.bin", 0x200001, 0x80000, CRC(41326c0d) SHA1(64bbecb560d2795ae5292776604ea318a9ae53a6) ) /* Plane 1 */
-	ROM_LOAD32_BYTE( "018-c8.bin", 0x200003, 0x80000, CRC(ed3b1f04) SHA1(0cb0d30e294e7ff398d553d0f08befb53ac65269) ) /* Plane 3 */
+	ROM_LOAD32_BYTE( "018_c1_2505.c1", 0x000000, 0x80000, CRC(3a441c6a) SHA1(0347d47a689af67426be42b4c99da101ee01ce11) ) /* Plane 0 */
+	ROM_LOAD32_BYTE( "018_c2_3f55.c2", 0x000002, 0x80000, CRC(bb72404b) SHA1(7620fccc50ecacf732bb1382abef42212d369f8c) ) /* Plane 2 */
+	ROM_LOAD32_BYTE( "018_c3_a20d.c3", 0x000001, 0x80000, CRC(87bffd2f) SHA1(0f7c835029a3f561861a1a07987dad23a32a899c) ) /* Plane 1 */
+	ROM_LOAD32_BYTE( "018_c4_c6e1.c4", 0x000003, 0x80000, CRC(33803163) SHA1(888ba63618a2ca541883a612f0c75ffa96f1c528) ) /* Plane 3 */
+	ROM_LOAD32_BYTE( "018_c5_2cd1.c5", 0x200000, 0x80000, CRC(74391952) SHA1(0f7451ff74901e7250214a7604a37add56ad7e1f) ) /* Plane 0 */
+	ROM_LOAD32_BYTE( "018_c6_8135.c6", 0x200002, 0x80000, CRC(95e220e6) SHA1(cef4f7c697ab6d20e1b5c85df773d0f1a79e3008) ) /* Plane 2 */
+	ROM_LOAD32_BYTE( "018_c7_d009.c7", 0x200001, 0x80000, CRC(41326c0d) SHA1(64bbecb560d2795ae5292776604ea318a9ae53a6) ) /* Plane 1 */
+	ROM_LOAD32_BYTE( "018_c8_dc63.c8", 0x200003, 0x80000, CRC(ed3b1f04) SHA1(0cb0d30e294e7ff398d553d0f08befb53ac65269) ) /* Plane 3 */
 ROM_END
 
 ROM_START( burningfp ) /* early prototype - all roms were hand labeled with CRCs, dumps verified against them */ /* AES VERSION */
@@ -3833,6 +3833,31 @@ ROM_START( rbff1a ) /* MVS VERSION */
 	ROM_LOAD16_BYTE( "095-c8.c8", 0x1800001, 0x200000, CRC(4e6beb6c) SHA1(c0ac7cfc832ace6ad52c58f5da3a8101baead749) ) /* Plane 2,3 */ /* TC5316200 */
 ROM_END
 
+ROM_START( rbff1k ) /* KOREAN VERSION */
+	ROM_REGION( 0x300000, "cslot1:maincpu", ROMREGION_BE|ROMREGION_16BIT )
+	ROM_LOAD16_WORD_SWAP( "095-p1k.p1",  0x000000, 0x100000, CRC(f705364b) SHA1(2668e15663a2c7ec7396f40e4f5f454505968ce8) ) /* TC538200 */
+	ROM_LOAD16_WORD_SWAP( "095-p2.sp2", 0x100000, 0x200000, CRC(cc15826e) SHA1(44d6ac6c0ca697a6f367dcfd809b1e1771cb0635) ) /* TC5316200 */
+
+	NEO_SFIX_128K( "095-s1.s1", CRC(b6bf5e08) SHA1(b527355c35ea097f3448676f2ffa65b8e56ae30c) ) /* TC531000 */
+
+	NEO_BIOS_AUDIO_128K( "095-m1.m1", CRC(653492a7) SHA1(39e511fb9ed5d2135dc8428a31d0baafb2ab36e0) ) /* TC531001 */
+
+	ROM_REGION( 0xc00000, "cslot1:ymsnd", 0 )
+	ROM_LOAD( "069-v1.v1", 0x000000, 0x400000, CRC(2bdbd4db) SHA1(5f4fecf69c2329d699cbd45829c19303b1e2a80e) ) /* TC5332204 */
+	ROM_LOAD( "069-v2.v2", 0x400000, 0x400000, CRC(a698a487) SHA1(11b8bc53bc26a51f4a408e900e3769958625c4ed) ) /* TC5332204 */
+	ROM_LOAD( "095-v3.v3", 0x800000, 0x400000, CRC(189d1c6c) SHA1(f0b8cd1ee40ea3feeb2800f0723b451ec8240203) ) /* TC5332201 */
+
+	ROM_REGION( 0x1c00000, "cslot1:sprites", 0 )
+	ROM_LOAD16_BYTE( "069-c1.c1", 0x0000000, 0x400000, CRC(e302f93c) SHA1(d8610b14900b2b8fe691b67ca9b1abb335dbff74) ) /* Plane 0,1 */ /* TC5332205 */
+	ROM_LOAD16_BYTE( "069-c2.c2", 0x0000001, 0x400000, CRC(1053a455) SHA1(69501bfac68739e63d798045b812badd251d57b8) ) /* Plane 2,3 */ /* TC5332205 */
+	ROM_LOAD16_BYTE( "069-c3.c3", 0x0800000, 0x400000, CRC(1c0fde2f) SHA1(cf6c2ef56c03a861de3b0b6dc0d7c9204d947f9d) ) /* Plane 0,1 */ /* TC5332205 */
+	ROM_LOAD16_BYTE( "069-c4.c4", 0x0800001, 0x400000, CRC(a25fc3d0) SHA1(83cb349e2f1032652060b233e741fb893be5af16) ) /* Plane 2,3 */ /* TC5332205 */
+	ROM_LOAD16_BYTE( "095-c5.c5", 0x1000000, 0x400000, CRC(8b9b65df) SHA1(e2a7e20855501f240bcd22f5cc92fcb4a9806abe) ) /* Plane 0,1 */ /* TC5332202 */
+	ROM_LOAD16_BYTE( "095-c6.c6", 0x1000001, 0x400000, CRC(3e164718) SHA1(53217f938c8964c1ca68a6fd5249c4169a5ac8e6) ) /* Plane 2,3 */ /* TC5332202 */
+	ROM_LOAD16_BYTE( "095-c7.c7", 0x1800000, 0x200000, CRC(ca605e12) SHA1(5150b835247fd705bc1dece97d423d9c20a51416) ) /* Plane 0,1 */ /* TC5316200 */
+	ROM_LOAD16_BYTE( "095-c8.c8", 0x1800001, 0x200000, CRC(4e6beb6c) SHA1(c0ac7cfc832ace6ad52c58f5da3a8101baead749) ) /* Plane 2,3 */ /* TC5316200 */
+ROM_END
+
 /****************************************
  ID-0096
  . NGM-096
@@ -8705,6 +8730,7 @@ GAME( 1995, samsho3h,   samsho3,  neobase,   neogeo, neogeo_state,   neogeo,   R
 GAME( 1995, fswords,    samsho3,  neobase,   neogeo, neogeo_state,   neogeo,   ROT0, "SNK", "Fighters Swords (Korean release of Samurai Shodown III)", MACHINE_SUPPORTS_SAVE )
 GAME( 1995, rbff1,      neogeo,   neobase,   neogeo, neogeo_state,   neogeo,   ROT0, "SNK", "Real Bout Fatal Fury / Real Bout Garou Densetsu (NGM-095 ~ NGH-095)", MACHINE_SUPPORTS_SAVE )
 GAME( 1995, rbff1a,     rbff1,    neobase,   neogeo, neogeo_state,   neogeo,   ROT0, "SNK", "Real Bout Fatal Fury / Real Bout Garou Densetsu (bug fix revision)", MACHINE_SUPPORTS_SAVE )
+GAME( 1995, rbff1k,     rbff1,    neobase,   neogeo, neogeo_state,   neogeo,   ROT0, "SNK", "Real Bout Fatal Fury / Real Bout Garou Densetsu (Korean release)", MACHINE_SUPPORTS_SAVE )
 GAME( 1996, aof3,       neogeo,   neobase,   neogeo, neogeo_state,   neogeo,   ROT0, "SNK", "Art of Fighting 3 - The Path of the Warrior / Art of Fighting - Ryuuko no Ken Gaiden", MACHINE_SUPPORTS_SAVE )
 GAME( 1996, aof3k,      aof3,     neobase,   neogeo, neogeo_state,   neogeo,   ROT0, "SNK", "Art of Fighting 3 - The Path of the Warrior (Korean release)", MACHINE_SUPPORTS_SAVE ) // no Japanese title / mode
 GAME( 1996, kof96,      neogeo,   neobase,   neogeo, neogeo_state,   neogeo,   ROT0, "SNK", "The King of Fighters '96 (NGM-214)", MACHINE_SUPPORTS_SAVE )
@@ -8730,7 +8756,7 @@ GAME( 1998, rbff2,      neogeo,   neobase,   neogeo, neogeo_state,   neogeo,   R
 GAME( 1998, rbff2h,     rbff2,    neobase,   neogeo, neogeo_state,   neogeo,   ROT0, "SNK", "Real Bout Fatal Fury 2 - The Newcomers / Real Bout Garou Densetsu 2 - The Newcomers (NGH-2400)", MACHINE_SUPPORTS_SAVE )
 GAME( 1998, rbff2k,     rbff2,    neobase,   neogeo, neogeo_state,   neogeo,   ROT0, "SNK", "Real Bout Fatal Fury 2 - The Newcomers (Korean release)", MACHINE_SUPPORTS_SAVE ) // no Japanese title / mode
 GAME( 1998, mslug2,     neogeo,   neobase,   neogeo, neogeo_state,   neogeo,   ROT0, "SNK", "Metal Slug 2 - Super Vehicle-001/II (NGM-2410 ~ NGH-2410)", MACHINE_SUPPORTS_SAVE )
-GAME( 2015, mslug2t,    mslug2,   neobase,   neogeo, neogeo_state,   neogeo,   ROT0, "Hack", "Metal Slug 2 Turbo (NGM-9410)", MACHINE_SUPPORTS_SAVE )
+GAME( 2015, mslug2t,    mslug2,   neobase,   neogeo, neogeo_state,   neogeo,   ROT0, "hack (trap15)", "Metal Slug 2 Turbo (NGM-9410) (hack)", MACHINE_SUPPORTS_SAVE )
 GAME( 1998, kof98,      neogeo,   kof98,     neogeo, neogeo_state,   neogeo,   ROT0, "SNK", "The King of Fighters '98 - The Slugfest / King of Fighters '98 - Dream Match Never Ends (NGM-2420)", MACHINE_SUPPORTS_SAVE )
 GAME( 1998, kof98a,     kof98,    kof98,     neogeo, neogeo_state,   neogeo,   ROT0, "SNK", "The King of Fighters '98 - The Slugfest / King of Fighters '98 - Dream Match Never Ends (NGM-2420, alt board)", MACHINE_SUPPORTS_SAVE )
 GAME( 1998, kof98k,     kof98,    kof98,     neogeo, neogeo_state,   neogeo,   ROT0, "SNK", "The King of Fighters '98 - The Slugfest / King of Fighters '98 - Dream Match Never Ends (Korean board)", MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/drivers/neptunp2.cpp b/src/mame/drivers/neptunp2.cpp
index 2567188..4090216 100644
--- a/src/mame/drivers/neptunp2.cpp
+++ b/src/mame/drivers/neptunp2.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /***************************************************************************
 
diff --git a/src/mame/drivers/nmk16.cpp b/src/mame/drivers/nmk16.cpp
index 0117753..5004622 100644
--- a/src/mame/drivers/nmk16.cpp
+++ b/src/mame/drivers/nmk16.cpp
@@ -1124,28 +1124,20 @@ ADDRESS_MAP_END
 
 static ADDRESS_MAP_START( atombjt_map, AS_PROGRAM, 16, nmk16_state )
 	AM_RANGE(0x000000, 0x03ffff) AM_ROM
-
-	AM_RANGE(0x0C2010, 0x0C2011) AM_READ_PORT("IN0")
-	AM_RANGE(0x0C2012, 0x0C2013) AM_READ(atombjt_unkr_r)
-	AM_RANGE(0x0C2014, 0x0C2015) AM_READ(atombjt_unkr_r)
-
-	AM_RANGE(0x0C2016, 0x0C2017) AM_READ_PORT("DSW1")
-	AM_RANGE(0x0C2018, 0x0C2019) AM_READ_PORT("DSW2")
-
-	AM_RANGE(0x100000, 0x101fff) AM_RAM
-
-	AM_RANGE(0x080000, 0x080001) AM_READ_PORT("IN0")
-	AM_RANGE(0x080002, 0x080003) AM_READ_PORT("IN1")
-
-	AM_RANGE(0x080014, 0x080015) AM_WRITE(nmk_flipscreen_w)
-//  AM_RANGE(0x084000, 0x084001) AM_DEVREADWRITE8("oki1", okim6295_device, read, write, 0x00ff)
-//  AM_RANGE(0x084010, 0x084011) AM_DEVREADWRITE8("oki2", okim6295_device, read, write, 0x00ff)
-//  AM_RANGE(0x084020, 0x08402f) AM_DEVWRITE("nmk112", nmk112_device, okibank_lsb_w)
+	AM_RANGE(0x080014, 0x080015) AM_NOP // always 1 in this bootleg. Flip-screen switch not present according to dip sheet.
 	AM_RANGE(0x088000, 0x0887ff) AM_RAM_DEVWRITE("palette", palette_device, write) AM_SHARE("palette")
 	AM_RANGE(0x094000, 0x094001) AM_WRITE(nmk_tilebank_w)
 	AM_RANGE(0x094002, 0x094003) AM_WRITENOP    /* IRQ enable? */
 	AM_RANGE(0x09c000, 0x09cfff) AM_MIRROR(0x1000) AM_RAM_WRITE(nmk_bgvideoram0_w) AM_SHARE("nmk_bgvideoram0")
+	AM_RANGE(0x0c2010, 0x0c2011) AM_READ_PORT("IN0")
+	AM_RANGE(0x0c2012, 0x0c2013) AM_READ_PORT("IN1")
+	AM_RANGE(0x0c2014, 0x0c2015) AM_READ(atombjt_unkr_r)
+	AM_RANGE(0x0c2016, 0x0c2017) AM_READ_PORT("DSW1")
+	AM_RANGE(0x0c2018, 0x0c2019) AM_READ_PORT("DSW2")
+//  AM_RANGE(0x0c201c, 0x0c201d) // oki banking related?
+	AM_RANGE(0x0c201e, 0x0c201f) AM_DEVREADWRITE8("oki1", okim6295_device, read, write, 0x00ff)
 	AM_RANGE(0x0f0000, 0x0fffff) AM_RAM AM_SHARE("mainram")
+	AM_RANGE(0x100000, 0x101fff) AM_RAM
 ADDRESS_MAP_END
 
 static INPUT_PORTS_START( vandyke )
@@ -2956,6 +2948,20 @@ static INPUT_PORTS_START( bjtwin )
 	PORT_DIPSETTING(    0x00, DEF_STR( Free_Play ) )
 INPUT_PORTS_END
 
+static INPUT_PORTS_START( atombjt ) // verified with dip sheet
+	PORT_INCLUDE(bjtwin)
+
+	PORT_MODIFY("DSW1")
+	PORT_DIPNAME( 0x01, 0x00, DEF_STR( Unused ) )       PORT_DIPLOCATION("SW1:8")
+	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
+	PORT_DIPSETTING(    0x01, DEF_STR( On ) )
+
+	PORT_MODIFY("DSW2")
+	PORT_DIPNAME( 0x01, 0x00, DEF_STR( Unused ) )       PORT_DIPLOCATION("SW2:8")
+	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
+	PORT_DIPSETTING(    0x01, DEF_STR( On ) )
+INPUT_PORTS_END
+
 static INPUT_PORTS_START( nouryoku )
 	PORT_START("IN0")
 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 )
@@ -4633,7 +4639,7 @@ static MACHINE_CONFIG_START( atombjt, nmk16_state )
 	/* sound hardware */
 	MCFG_SPEAKER_STANDARD_MONO("mono")
 
-	MCFG_OKIM6295_ADD("oki1", 16000000/4, OKIM6295_PIN7_LOW) // ?? mhz, I see no 16 crystal
+	MCFG_OKIM6295_ADD("oki1", 10000000/8, OKIM6295_PIN7_LOW) // divider and pin not verified
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.20)
 MACHINE_CONFIG_END
 
@@ -7914,11 +7920,11 @@ GAME( 1992, sabotenb, 0,        bjtwin,   sabotenb, nmk16_state, nmk,      ROT0,
 GAME( 1992, sabotenba,sabotenb, bjtwin,   sabotenb, nmk16_state, nmk,      ROT0,   "NMK / Tecmo",                  "Saboten Bombers (set 2)", MACHINE_NO_COCKTAIL )
 GAME( 1992, cactus,   sabotenb, bjtwin,   sabotenb, nmk16_state, nmk,      ROT0,   "bootleg",                      "Cactus (bootleg of Saboten Bombers)", MACHINE_NO_COCKTAIL ) // PCB marked 'Cactus', no title screen
 
-GAME( 1993, bjtwin,   0,        bjtwin,   bjtwin, nmk16_state,   bjtwin,   ROT270, "NMK",                          "Bombjack Twin (set 1)", MACHINE_NO_COCKTAIL )
-GAME( 1993, bjtwina,  bjtwin,   bjtwin,   bjtwin, nmk16_state,   bjtwin,   ROT270, "NMK",                          "Bombjack Twin (set 2)", MACHINE_NO_COCKTAIL )
-GAME( 1993, bjtwinp,  bjtwin,   bjtwin,   bjtwin, driver_device, 0,        ROT270, "NMK",                          "Bombjack Twin (prototype? with adult pictures, set 1)", MACHINE_NO_COCKTAIL ) // Cheap looking PCB, but Genuine NMK PCB, GFX aren't encrypted (maybe Korean version not proto?)
-GAME( 1993, bjtwinpa, bjtwin,   bjtwin,   bjtwin, nmk16_state,   bjtwin,   ROT270, "NMK",                          "Bombjack Twin (prototype? with adult pictures, set 2)", MACHINE_NO_COCKTAIL ) // same PCB as above, different program revision, GFX are encrypted
-GAME( 1993, atombjt,  bjtwin,   atombjt,  bjtwin, driver_device, 0,        ROT270, "bootleg",                      "Atom (bootleg of Bombjack Twin)", MACHINE_NO_COCKTAIL | MACHINE_NOT_WORKING ) // some non-trivial mods to the gfx and sound hw (playmark hardware?)
+GAME( 1993, bjtwin,   0,        bjtwin,   bjtwin,  nmk16_state,   bjtwin,   ROT270, "NMK",                          "Bombjack Twin (set 1)", MACHINE_NO_COCKTAIL )
+GAME( 1993, bjtwina,  bjtwin,   bjtwin,   bjtwin,  nmk16_state,   bjtwin,   ROT270, "NMK",                          "Bombjack Twin (set 2)", MACHINE_NO_COCKTAIL )
+GAME( 1993, bjtwinp,  bjtwin,   bjtwin,   bjtwin,  driver_device, 0,        ROT270, "NMK",                          "Bombjack Twin (prototype? with adult pictures, set 1)", MACHINE_NO_COCKTAIL ) // Cheap looking PCB, but Genuine NMK PCB, GFX aren't encrypted (maybe Korean version not proto?)
+GAME( 1993, bjtwinpa, bjtwin,   bjtwin,   bjtwin,  nmk16_state,   bjtwin,   ROT270, "NMK",                          "Bombjack Twin (prototype? with adult pictures, set 2)", MACHINE_NO_COCKTAIL ) // same PCB as above, different program revision, GFX are encrypted
+GAME( 1993, atombjt,  bjtwin,   atombjt,  atombjt, driver_device, 0,        ROT270, "bootleg (Kyon K.)",            "Atom (bootleg of Bombjack Twin)", MACHINE_NO_COCKTAIL | MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING ) // some non-trivial mods to the gfx and sound hw (playmark hardware?)
 
 
 GAME( 1995, nouryoku, 0,        bjtwin,   nouryoku, nmk16_state,   nmk,      ROT0,   "Tecmo",                        "Nouryoku Koujou Iinkai", MACHINE_NO_COCKTAIL )
diff --git a/src/mame/drivers/nycaptor.cpp b/src/mame/drivers/nycaptor.cpp
index 77d57cb..eaff020 100644
--- a/src/mame/drivers/nycaptor.cpp
+++ b/src/mame/drivers/nycaptor.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /***************************************************************************
     N.Y. Captor - Taito '85
diff --git a/src/mame/drivers/ob68k1a.cpp b/src/mame/drivers/ob68k1a.cpp
index 992eb10..a5e41b8 100644
--- a/src/mame/drivers/ob68k1a.cpp
+++ b/src/mame/drivers/ob68k1a.cpp
@@ -224,8 +224,7 @@ static MACHINE_CONFIG_START( ob68k1a, ob68k1a_state )
 	// devices
 	MCFG_DEVICE_ADD(MC6821_0_TAG, PIA6821, 0)
 	MCFG_DEVICE_ADD(MC6821_1_TAG, PIA6821, 0)
-	MCFG_DEVICE_ADD(MC6840_TAG, PTM6840, 0)
-	MCFG_PTM6840_INTERNAL_CLOCK(XTAL_10MHz/10)
+	MCFG_DEVICE_ADD(MC6840_TAG, PTM6840, XTAL_10MHz/10)
 	MCFG_PTM6840_EXTERNAL_CLOCKS(0, 0, 0)
 
 	MCFG_DEVICE_ADD(MC6850_0_TAG, ACIA6850, 0)
diff --git a/src/mame/drivers/othello.cpp b/src/mame/drivers/othello.cpp
index 3a244df..49adc51 100644
--- a/src/mame/drivers/othello.cpp
+++ b/src/mame/drivers/othello.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /*
 
diff --git a/src/mame/drivers/pachifev.cpp b/src/mame/drivers/pachifev.cpp
index 3357707..d3b5fdc 100644
--- a/src/mame/drivers/pachifev.cpp
+++ b/src/mame/drivers/pachifev.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /**********************************************************************************************************
 
diff --git a/src/mame/drivers/pacman.cpp b/src/mame/drivers/pacman.cpp
index 7f3c2a4..8ee0ad6 100644
--- a/src/mame/drivers/pacman.cpp
+++ b/src/mame/drivers/pacman.cpp
@@ -29,7 +29,7 @@
         * MTV Rock-N-Roll Trivia (Part 2)
         * Woodpecker
         * Pacman Club / Club Lambada
-
+        * Eeekk!
 
     Known issues:
         * Mystery items in Ali Baba don't work correctly because of protection.
@@ -37,7 +37,6 @@
           Also need 4-players extra inputs.
 
     Known to exist but dumps needed
-        * Eeeek!
         * Ms Pac Plus
         * Ms Pac Man Twin
         * MTV Rock-N-Roll Trivia (Part 2), 1 bad rom. It's not a bad dump, the rom is bad.
@@ -345,10 +344,9 @@ Boards:
 #include "machine/watchdog.h"
 #include "sound/ay8910.h"
 #include "sound/sn76496.h"
-#include "machine/acitya.h"
+#include "machine/epos.h"
 #include "machine/jumpshot.h"
 #include "machine/pacplus.h"
-#include "machine/theglobp.h"
 
 
 /*************************************
@@ -1428,13 +1426,8 @@ static ADDRESS_MAP_START( nmouse_portmap, AS_IO, 8, pacman_state )
 	AM_RANGE(0x00, 0x00) AM_WRITE(nmouse_interrupt_vector_w)
 ADDRESS_MAP_END
 
-static ADDRESS_MAP_START( theglobp_portmap, AS_IO, 8, pacman_state )
-	AM_RANGE(0x00, 0xff) AM_READ(theglobp_decrypt_rom)   /* Switch protection logic */
-	AM_IMPORT_FROM(writeport)
-ADDRESS_MAP_END
-
-static ADDRESS_MAP_START( acitya_portmap, AS_IO, 8, pacman_state )
-	AM_RANGE(0x00, 0xff) AM_READ(acitya_decrypt_rom) /* Switch protection logic */
+static ADDRESS_MAP_START( epos_portmap, AS_IO, 8, pacman_state )
+	AM_RANGE(0x00, 0xff) AM_READ(epos_decryption_w)   /* Switch protection logic */
 	AM_IMPORT_FROM(writeport)
 ADDRESS_MAP_END
 
@@ -2376,6 +2369,39 @@ static INPUT_PORTS_START( theglobp )
 INPUT_PORTS_END
 
 
+static INPUT_PORTS_START( eeekk )
+	PORT_INCLUDE(pacman)
+	PORT_MODIFY("IN0")
+	PORT_SERVICE_NO_TOGGLE( 0x10, 0x10 )
+	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
+	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
+
+	PORT_MODIFY("IN1")
+	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
+	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1)
+
+	PORT_MODIFY("DSW1")
+	PORT_DIPNAME( 0x03, 0x03, DEF_STR(Lives) )      PORT_DIPLOCATION("SW:1,2")
+	PORT_DIPSETTING(    0x03, "3" )
+	PORT_DIPSETTING(    0x02, "4" )
+	PORT_DIPSETTING(    0x01, "5" )
+	PORT_DIPSETTING(    0x00, "6" )
+	PORT_DIPNAME( 0x1c, 0x10, DEF_STR( Difficulty ) )        PORT_DIPLOCATION("SW:3,4,5")
+	PORT_DIPSETTING(    0x00, "8" )
+	PORT_DIPSETTING(    0x04, "7" )
+	PORT_DIPSETTING(    0x08, "6" )
+	PORT_DIPSETTING(    0x0c, "5" )
+	PORT_DIPSETTING(    0x10, "4" )
+	PORT_DIPSETTING(    0x14, "3" )
+	PORT_DIPSETTING(    0x18, "2" )
+	PORT_DIPSETTING(    0x1c, "1" )
+	PORT_DIPNAME( 0x20, 0x00, DEF_STR(Demo_Sounds) )      PORT_DIPLOCATION("SW:6")
+	PORT_DIPSETTING(    0x00, DEF_STR(On) )
+	PORT_DIPSETTING(    0x20, DEF_STR(Off) )
+	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
+	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
+INPUT_PORTS_END
+
 static INPUT_PORTS_START( vanvan )
 	PORT_START("IN0")
 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_4WAY
@@ -3651,7 +3677,7 @@ static MACHINE_CONFIG_DERIVED( theglobp, pacman )
 	/* basic machine hardware */
 	MCFG_CPU_MODIFY("maincpu")
 	MCFG_CPU_PROGRAM_MAP(epos_map)
-	MCFG_CPU_IO_MAP(theglobp_portmap)
+	MCFG_CPU_IO_MAP(epos_portmap)
 
 	MCFG_MACHINE_START_OVERRIDE(pacman_state,theglobp)
 	MCFG_MACHINE_RESET_OVERRIDE(pacman_state,theglobp)
@@ -3663,13 +3689,25 @@ static MACHINE_CONFIG_DERIVED( acitya, pacman )
 	/* basic machine hardware */
 	MCFG_CPU_MODIFY("maincpu")
 	MCFG_CPU_PROGRAM_MAP(epos_map)
-	MCFG_CPU_IO_MAP(acitya_portmap)
+	MCFG_CPU_IO_MAP(epos_portmap)
 
 	MCFG_MACHINE_START_OVERRIDE(pacman_state,acitya)
 	MCFG_MACHINE_RESET_OVERRIDE(pacman_state,acitya)
 MACHINE_CONFIG_END
 
 
+static MACHINE_CONFIG_DERIVED( eeekk, pacman )
+
+	/* basic machine hardware */
+	MCFG_CPU_MODIFY("maincpu")
+	MCFG_CPU_PROGRAM_MAP(epos_map)
+	MCFG_CPU_IO_MAP(epos_portmap)
+
+	MCFG_MACHINE_START_OVERRIDE(pacman_state,eeekk)
+	MCFG_MACHINE_RESET_OVERRIDE(pacman_state,eeekk)
+MACHINE_CONFIG_END
+
+
 static MACHINE_CONFIG_DERIVED( vanvan, pacman )
 
 	/* basic machine hardware */
@@ -6029,6 +6067,9 @@ ROM_START( beastfp )
 	ROM_LOAD( "beastf.5e",    0x0000, 0x1000, CRC(5654dc34) SHA1(fc2336b951a3ab48d4fc4f36a8dd80e79e8ca1a0) )
 	ROM_LOAD( "beastf.5f",    0x1000, 0x1000, CRC(1b30ca61) SHA1(8495d8a280346246f00c4f1dc42ab5a2a02c5863) )
 
+	ROM_REGION( 0x002c, "epos_pal10h8", 0)
+	ROM_LOAD( "beastf.ic4",   0x0000, 0x002c, CRC(a6ab926d) SHA1(a8c2ddce2d595cecf057b37916f2f897de8a0e4e) ) // pal10h8
+
 	ROM_REGION( 0x0120, "proms", 0 )
 	ROM_LOAD( "glob.7f",      0x0000, 0x0020, CRC(1f617527) SHA1(448845cab63800a05fcb106897503d994377f78f) )
 	ROM_LOAD( "glob.4a",      0x0020, 0x0100, CRC(28faa769) SHA1(7588889f3102d4e0ca7918f536556209b2490ea1) )
@@ -6039,6 +6080,28 @@ ROM_START( beastfp )
 ROM_END
 
 
+ROM_START( eeekk ) // Pac-Man PCB conversion kit. Includes a small daughtercard (2 roms + 4 PLDs, plugs in through the Z80 socket), 2 roms + 2 BPROMs
+	ROM_REGION( 0x20000, "maincpu", 0 )
+	ROM_LOAD( "u_2_eeekk_pg03094.u2",   0x0000, 0x2000, CRC(701e37f2) SHA1(15bbd983e9112ce15dd229f126f2bccfa8b9807c) ) // encrypted
+	ROM_LOAD( "u_3_eeekk_pg03094.u3",   0x2000, 0x2000, CRC(bcf524ae) SHA1(be2a1a2984ea1439c63d8c353e4ae85bf42c8a55) ) // encrypted
+
+	ROM_REGION( 0x2000, "gfx1", 0 )
+	ROM_LOAD( "5_e_eeekk_pg03094.5e",   0x0000, 0x1000, CRC(780183a8) SHA1(8466d75d79b3c87db143f5c2e8b58dad1d2e501c) )
+	ROM_LOAD( "5_f_eeekk_pg03094.5f",   0x1000, 0x1000, CRC(418526e4) SHA1(a95764e216ccdaca0631604e1101ba91884effde) )
+
+	ROM_REGION( 0x002c, "epos_pal10h8", 0)
+	ROM_LOAD( "eeekk.ic4",    0x0000, 0x002c, CRC(f588ba4e) SHA1(07d74da02172789ccd1fead2b5afe8ce72c5149d) ) // pal10h8
+
+	ROM_REGION( 0x0120, "proms", 0 )
+	ROM_LOAD( "7_f_eeekk.7f",     0x0000, 0x0020, CRC(c64c8a53) SHA1(55e7b88cb1ce129e8154722a489d76c38924d3f1) ) // 82s123
+	ROM_LOAD( "4_a_eeekk.4a",     0x0020, 0x0100, CRC(a5044ded) SHA1(566bd06674bf8069dc633102493c9991b64e4379) ) // 82s126
+
+	ROM_REGION( 0x0200, "namco", 0 )    /* sound PROMs */
+	ROM_LOAD( "82s126.1m",    0x0000, 0x0100, CRC(a9cc86bf) SHA1(bbcec0570aeceb582ff8238a4bc8546a23430081) ) // 82s126
+	ROM_LOAD( "82s126.3m",    0x0100, 0x0100, CRC(77245b66) SHA1(0c4d0bee858b97632411c440bea6948a74759746) ) // 82s126 - timing - not used
+ROM_END
+
+
 ROM_START( vanvan )
 	ROM_REGION( 0x10000, "maincpu", 0 )
 	ROM_LOAD( "van-1.50",     0x0000, 0x1000, CRC(cf1b2df0) SHA1(938b4434c0129cf9151f829901d00e47dca68956) )
@@ -7284,6 +7347,7 @@ GAME( 1983, theglobp, suprglob, theglobp, theglobp, driver_device, 0,        ROT
 GAME( 1983, sprglobp, suprglob, theglobp, theglobp, driver_device, 0,        ROT90,  "Epos Corporation", "Super Glob (Pac-Man hardware)", MACHINE_SUPPORTS_SAVE )
 GAME( 1983, sprglbpg, suprglob, pacman,   theglobp, driver_device, 0,        ROT90,  "bootleg", "Super Glob (Pac-Man hardware) (German bootleg)", MACHINE_SUPPORTS_SAVE )
 GAME( 1984, beastfp,  suprglob, theglobp, theglobp, driver_device, 0,        ROT90,  "Epos Corporation", "Beastie Feastie (conversion kit)", MACHINE_SUPPORTS_SAVE )
+GAME( 1984, eeekk,    0,        eeekk,    eeekk,    driver_device, 0,        ROT90,  "Epos Corporation", "Eeekk!", MACHINE_SUPPORTS_SAVE )
 
 GAME( 1984, drivfrcp, 0,        drivfrcp, drivfrcp, pacman_state,  drivfrcp, ROT90,  "Shinkai Inc. (Magic Electronics Inc. license)", "Driving Force (Pac-Man conversion)", MACHINE_SUPPORTS_SAVE )
 
diff --git a/src/mame/drivers/pc.cpp b/src/mame/drivers/pc.cpp
index a6d5d3b..b0e4fcf 100644
--- a/src/mame/drivers/pc.cpp
+++ b/src/mame/drivers/pc.cpp
@@ -330,6 +330,60 @@ static MACHINE_CONFIG_DERIVED(m15, pccga)
 	MCFG_RAM_EXTRA_OPTIONS("16K, 160K, 304K")
 MACHINE_CONFIG_END
 
+static MACHINE_CONFIG_START( laser_turbo_xt, pc_state )
+	MCFG_CPU_PC(pc8, pc8, I8088, XTAL_14_31818MHz/3) /* 4,77 MHz */
+
+	MCFG_IBM5160_MOTHERBOARD_ADD("mb","maincpu")
+	MCFG_DEVICE_INPUT_DEFAULTS(pccga)
+
+	MCFG_ISA8_SLOT_ADD("mb:isa", "isa1", pc_isa8_cards, "cga", false)
+	MCFG_ISA8_SLOT_ADD("mb:isa", "isa2", pc_isa8_cards, "com", false) // Multi I/O card (includes FDC)
+	MCFG_ISA8_SLOT_ADD("mb:isa", "isa3", pc_isa8_cards, "fdc_xt", false)
+	MCFG_ISA8_SLOT_ADD("mb:isa", "isa4", pc_isa8_cards, nullptr, false)
+	MCFG_ISA8_SLOT_ADD("mb:isa", "isa5", pc_isa8_cards, nullptr, false)
+	MCFG_ISA8_SLOT_ADD("mb:isa", "isa6", pc_isa8_cards, nullptr, false)
+	MCFG_ISA8_SLOT_ADD("mb:isa", "isa7", pc_isa8_cards, nullptr, false)
+	MCFG_ISA8_SLOT_ADD("mb:isa", "isa8", pc_isa8_cards, nullptr, false)
+
+	/* keyboard */
+	MCFG_PC_KBDC_SLOT_ADD("mb:pc_kbdc", "kbd", pc_xt_keyboards, STR_KBD_IBM_PC_XT_83)
+
+	/* internal ram */
+	MCFG_RAM_ADD(RAM_TAG)
+	MCFG_RAM_DEFAULT_SIZE("640K")
+	MCFG_RAM_EXTRA_OPTIONS("512K,768K,896K,1024K,1408K,1536K,1664K")
+
+	/* software lists */
+	MCFG_SOFTWARE_LIST_ADD("disk_list","ibm5150")
+MACHINE_CONFIG_END
+
+static MACHINE_CONFIG_START( laser_xt3, pc_state )
+	MCFG_CPU_PC(pc8, pc8, I8088, XTAL_14_31818MHz/3) /* 4,77 MHz */
+
+	MCFG_IBM5160_MOTHERBOARD_ADD("mb","maincpu")
+	MCFG_DEVICE_INPUT_DEFAULTS(pccga)
+
+	MCFG_ISA8_SLOT_ADD("mb:isa", "isa1", pc_isa8_cards, "cga", false)
+	MCFG_ISA8_SLOT_ADD("mb:isa", "isa2", pc_isa8_cards, "com", false) // Multi I/O card (includes FDC)
+	MCFG_ISA8_SLOT_ADD("mb:isa", "isa3", pc_isa8_cards, "fdc_xt", false) // floppy drive A is 5.25" 360K and B is 3.5" 720K
+	MCFG_ISA8_SLOT_ADD("mb:isa", "isa4", pc_isa8_cards, nullptr, false)
+	MCFG_ISA8_SLOT_ADD("mb:isa", "isa5", pc_isa8_cards, nullptr, false)
+	MCFG_ISA8_SLOT_ADD("mb:isa", "isa6", pc_isa8_cards, nullptr, false)
+	MCFG_ISA8_SLOT_ADD("mb:isa", "isa7", pc_isa8_cards, nullptr, false)
+	MCFG_ISA8_SLOT_ADD("mb:isa", "isa8", pc_isa8_cards, nullptr, false)
+
+	/* keyboard */
+	MCFG_PC_KBDC_SLOT_ADD("mb:pc_kbdc", "kbd", pc_xt_keyboards, STR_KBD_IBM_PC_XT_83)
+
+	/* internal ram */
+	MCFG_RAM_ADD(RAM_TAG)
+	MCFG_RAM_DEFAULT_SIZE("640K")
+	MCFG_RAM_EXTRA_OPTIONS("512K,1024K,1536K,1664K")
+
+	/* software lists */
+	MCFG_SOFTWARE_LIST_ADD("disk_list","ibm5150")
+MACHINE_CONFIG_END
+
 ROM_START( bw230 )
 	ROM_REGION(0x10000,"bios", 0)
 	ROM_LOAD("bondwell.bin", 0xe000, 0x2000, CRC(d435a405) SHA1(a57c705d1144c7b61940b6f5c05d785c272fc9bb))
@@ -496,6 +550,17 @@ ROM_START( eagle1600 )
 	ROM_LOAD("eagle 1600 video char gen u301.bin", 0x00000, 0x1000, CRC(1a7e552f) SHA1(749058783eec9d96a70dc5fdbfccb56196f889dc))
 ROM_END
 
+ROM_START(laser_turbo_xt)
+	ROM_REGION(0x10000, "bios", 0)
+	ROM_LOAD("laser_turbo_xt.bin", 0x0e000, 0x02000, CRC(0a6121d3) SHA1(59b1f8dd6fe981ef9a7700adebf6e1adda7cee90)) // version 1.11 - 27c64d
+ROM_END
+
+ROM_START(laser_xt3)
+	ROM_REGION(0x10000, "bios", 0)
+	ROM_LOAD("laser_xt3.bin", 0x0e000, 0x02000, CRC(b45a7dd3) SHA1(62f17c408be0036d00a182e94c5c88b83d46b625)) // version 1.26 - 27c64
+ROM_END
+
+
 /***************************************************************************
 
   Game driver(s)
@@ -530,3 +595,6 @@ COMP( 198?, mbc16,      ibm5150,    0,          pccga,      pccga, driver_device
 COMP( 198?, ataripc3,   ibm5150,    0,          pccga,      pccga, driver_device,      0,      "Atari", "PC-3" , 0)
 COMP( 1989, ssam88s,    ibm5150,    0,          pccga,      pccga, driver_device,      0,      "Samsung", "Samtron 88S" , MACHINE_NOT_WORKING)
 COMP( 1983, eagle1600,  ibm5150,    0,          eagle1600,  pccga, driver_device,      0,      "Eagle", "1600" , MACHINE_NOT_WORKING)
+
+COMP ( 1988,    laser_turbo_xt,      ibm5150,    0,      laser_turbo_xt,      0,     driver_device,       0,          "VTech",  "Laser Turbo XT" , 0)
+COMP ( 1989,    laser_xt3,           ibm5150,    0,      laser_xt3,           0,     driver_device,       0,          "VTech",  "Laser XT/3" , 0)
diff --git a/src/mame/drivers/peplus.cpp b/src/mame/drivers/peplus.cpp
index 10078ec..930cc3e 100644
--- a/src/mame/drivers/peplus.cpp
+++ b/src/mame/drivers/peplus.cpp
@@ -2119,7 +2119,7 @@ PayTable   3K   STR  FL  FH  4K  SF  5K  RF  4D  RF  (Bonus)
 	ROM_LOAD( "cap435.u37", 0x0000, 0x0100, CRC(038cabc6) SHA1(c6514b4f9dbed6ab2631f563f7e00648661ebdbb) )
 ROM_END
 
-ROM_START( pepk1013 ) /* Normal board (non-plus) : Tens or Better (PK1013) */
+ROM_START( pepk1013 ) /* Normal board (non-plus) : Jacks or Better (PK1013) */
 /*
 PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 ----------------------------------------------------------
@@ -2238,7 +2238,7 @@ ROM_START( pepp0001 ) /* Normal board : Standard Draw Poker (PP0001) */
 PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 ----------------------------------------------------------
    BA       1    2    3    4    5   8  25  50 250    800
-  % Range: 93.8-95.8%  Optimum: 97.8%  Hit Frequency: 45.3%
+  % Range: 93.3-95.3%  Optimum: 97.3%  Hit Frequency: 45.5%
      Programs Available: PP0001
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
@@ -2503,7 +2503,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
      Programs Available: PP0038, X002121P
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0038_a45-a74.u68",   0x00000, 0x10000, CRC(85fe387e) SHA1(a0aa4cb422c04066d61d665943eced30b2eaf5b2) ) /* Game Version: A45, Library Version: A74 */
+	ROM_LOAD( "pp0038_a45-a74.u68",   0x00000, 0x10000, CRC(85fe387e) SHA1(a0aa4cb422c04066d61d665943eced30b2eaf5b2) ) /* Game Version: A45, Library Version: A74 - 10/23/95   @ IGT  L95-2288 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2004.u72",  0x00000, 0x8000, CRC(e5e40ea5) SHA1(e0d9e50b30cc0c25c932b2bf444990df1fb2c38c) ) /*  08/31/94   @ IGT  L95-0146  */
@@ -2650,7 +2650,7 @@ PayTable  10s+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
      Programs Available: PP0043, X000043P
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0043_a45-a74.u68",   0x00000, 0x10000, CRC(04051a88) SHA1(e7a9ec2ab7f6f575245d47ee10a03f39c887d1b3) ) /* Game Version: A45, Library Version: A74 */
+	ROM_LOAD( "pp0043_a45-a74.u68",   0x00000, 0x10000, CRC(04051a88) SHA1(e7a9ec2ab7f6f575245d47ee10a03f39c887d1b3) ) /* Game Version: A45, Library Version: A74 - 10/23/95   @ IGT  L95-2292 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2004.u72",  0x00000, 0x8000, CRC(e5e40ea5) SHA1(e0d9e50b30cc0c25c932b2bf444990df1fb2c38c) ) /*  08/31/94   @ IGT  L95-0146  */
@@ -2662,7 +2662,7 @@ PayTable  10s+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 	ROM_LOAD( "cap740.u50", 0x0000, 0x0100, CRC(6fe619c4) SHA1(49e43dafd010ce0fe9b2a63b96a4ddedcb933c6d) )
 ROM_END
 
-ROM_START( pepp0043a ) /* Normal board : 10's or Better (PP0043) - Multi Regional / Multi Currency - Tournament Mode capable */
+ROM_START( pepp0043a ) /* Normal board : 10's or Better (PP0043) - Multi Regional / Multi Currency - Tournament Mode capable - PSR Verified */
 /*
 PayTable  10s+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 ----------------------------------------------------------
@@ -2738,9 +2738,9 @@ PayTable  10s+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg1248.u72",  0x00000, 0x8000, CRC(4e2f9276) SHA1(25b84314e75408f9a057a89ac9154be7768813eb) ) /* Custom Gambler Downtown Reno card backs */
-	ROM_LOAD( "mgo-cg1248.u73",  0x08000, 0x8000, CRC(5ecfb257) SHA1(aebe9580434007cae52091eb1814ce201698a4b0) )
-	ROM_LOAD( "mbo-cg1248.u74",  0x10000, 0x8000, CRC(c4b84599) SHA1(e753537c4615b42aa726d19f19dfa934050ac54e) ) /* These graphics will work for many other standard poker sets */
-	ROM_LOAD( "mxo-cg1248.u75",  0x18000, 0x8000, CRC(ac2ddd3c) SHA1(ce76c77a3d8b5d71d272b9982d43a35e913b54de) ) /* However there is no support for Deuces Wild sets */
+	ROM_LOAD( "mgo-cg1248.u73",  0x08000, 0x8000, CRC(5ecfb257) SHA1(aebe9580434007cae52091eb1814ce201698a4b0) ) /* No support for Deuces Wild sets */
+	ROM_LOAD( "mbo-cg1248.u74",  0x10000, 0x8000, CRC(c4b84599) SHA1(e753537c4615b42aa726d19f19dfa934050ac54e) )
+	ROM_LOAD( "mxo-cg1248.u75",  0x18000, 0x8000, CRC(ac2ddd3c) SHA1(ce76c77a3d8b5d71d272b9982d43a35e913b54de) )
 
 	ROM_REGION( 0x100, "proms", 0 )
 	ROM_LOAD( "cap1248.u50", 0x0000, 0x0100, CRC(be238287) SHA1(9bfe601df8d3e40307c15a6b871e79f12fab3169) )
@@ -2759,9 +2759,9 @@ PayTable  10s+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg1150.u72",  0x00000, 0x8000, CRC(91186809) SHA1(1fc91926cf854411738128cb82d1fce6a8f8c8fd) ) /* Custom Par-A-Dice Riverboat Casino card backs */
-	ROM_LOAD( "mgo-cg1150.u73",  0x08000, 0x8000, CRC(a1e66166) SHA1(6dfa3952636fb6cd24c725139624571ab279221c) )
-	ROM_LOAD( "mbo-cg1150.u74",  0x10000, 0x8000, CRC(8c2c3c0e) SHA1(fe1f1648ff7751e75b874db83f4ec5f54e95083e) ) /* These graphics will work for many other standard poker sets */
-	ROM_LOAD( "mxo-cg1150.u75",  0x18000, 0x8000, CRC(ece41352) SHA1(3c7afb98254c05ce139ca9675ecb415641552371) ) /* However there is no support for Deuces Wild sets */
+	ROM_LOAD( "mgo-cg1150.u73",  0x08000, 0x8000, CRC(a1e66166) SHA1(6dfa3952636fb6cd24c725139624571ab279221c) ) /* No support for Deuces Wild sets */
+	ROM_LOAD( "mbo-cg1150.u74",  0x10000, 0x8000, CRC(8c2c3c0e) SHA1(fe1f1648ff7751e75b874db83f4ec5f54e95083e) )
+	ROM_LOAD( "mxo-cg1150.u75",  0x18000, 0x8000, CRC(ece41352) SHA1(3c7afb98254c05ce139ca9675ecb415641552371) )
 
 	ROM_REGION( 0x100, "proms", 0 )
 	ROM_LOAD( "cap1150.u50", 0x0000, 0x0100, NO_DUMP )
@@ -2781,9 +2781,9 @@ PayTable  10s+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg1072.u72",  0x00000, 0x8000, CRC(8e5cf3bf) SHA1(a8c2fde9105a37eddc218ae1476cdbfb0271e314) ) /* Custom Annie Oakley's Central City graphics */
-	ROM_LOAD( "mgo-cg1072.u73",  0x08000, 0x8000, CRC(a3c85c1b) SHA1(9b810c5779dde21db6da5bac5cf797bad65c2c1b) )
-	ROM_LOAD( "mbo-cg1072.u74",  0x10000, 0x8000, CRC(833371e1) SHA1(5d7a994aee61a751f89171885423276b86e872b6) ) /* These graphics will work for many other standard poker sets */
-	ROM_LOAD( "mxo-cg1072.u75",  0x18000, 0x8000, CRC(0df703b3) SHA1(2042251cc9c11687ff7fd920213a448974ff3050) ) /* However there is no support for Deuces Wild sets */
+	ROM_LOAD( "mgo-cg1072.u73",  0x08000, 0x8000, CRC(a3c85c1b) SHA1(9b810c5779dde21db6da5bac5cf797bad65c2c1b) ) /* No support for Deuces Wild sets */
+	ROM_LOAD( "mbo-cg1072.u74",  0x10000, 0x8000, CRC(833371e1) SHA1(5d7a994aee61a751f89171885423276b86e872b6) )
+	ROM_LOAD( "mxo-cg1072.u75",  0x18000, 0x8000, CRC(0df703b3) SHA1(2042251cc9c11687ff7fd920213a448974ff3050) )
 
 	ROM_REGION( 0x100, "proms", 0 )
 	ROM_LOAD( "cap1072.u50", 0x0000, 0x0100, NO_DUMP )
@@ -2803,9 +2803,9 @@ PayTable  10s+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg881.u72",   0x00000, 0x8000, CRC(282a029f) SHA1(42b35761839d6379ddfb4eed20f90d9f7b145e64) ) /* Custom Las Vegas Rio graphics */
-	ROM_LOAD( "mgo-cg881.u73",   0x08000, 0x8000, CRC(af433702) SHA1(fbd877c06eaab433332c94f135e13a8c041fa1a2) )
-	ROM_LOAD( "mbo-cg881.u74",   0x10000, 0x8000, CRC(c5b0a0b3) SHA1(a989d21f4b10a09d3cfd0bbb9f53b4ad326561b9) ) /* These graphics will work for many other standard poker sets */
-	ROM_LOAD( "mxo-cg881.u75",   0x18000, 0x8000, CRC(6a78bc1d) SHA1(7861465ab98df5219330d58a3e5a4bd37a393534) ) /* However there is no support for Deuces Wild sets */
+	ROM_LOAD( "mgo-cg881.u73",   0x08000, 0x8000, CRC(af433702) SHA1(fbd877c06eaab433332c94f135e13a8c041fa1a2) ) /* No support for Deuces Wild sets */
+	ROM_LOAD( "mbo-cg881.u74",   0x10000, 0x8000, CRC(c5b0a0b3) SHA1(a989d21f4b10a09d3cfd0bbb9f53b4ad326561b9) )
+	ROM_LOAD( "mxo-cg881.u75",   0x18000, 0x8000, CRC(6a78bc1d) SHA1(7861465ab98df5219330d58a3e5a4bd37a393534) )
 
 	ROM_REGION( 0x100, "proms", 0 )
 	ROM_LOAD( "cap881.u50", 0x0000, 0x0100, CRC(e51990d5) SHA1(41946722b61e955d37808761d451fc894e6adc8a) )
@@ -3046,7 +3046,7 @@ PayTable   Ks+  2P  3K  STR  FL  FH  4K  SF  RF  5K  RF  (Bonus)
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg834.u72",   0x00000, 0x8000, CRC(97d22af0) SHA1(0588f7772ac9447e4bf6b58804b2c34ca7014b60) ) /* Custom El Cortez card backs - 02/23/89   @ IGT  L89-0653  */
-	ROM_LOAD( "mgo-cg834.u73",   0x08000, 0x8000, CRC(502b1673) SHA1(a331fcc0f6705db836b4333ae28ff75296b6cf0d) )
+	ROM_LOAD( "mgo-cg834.u73",   0x08000, 0x8000, CRC(502b1673) SHA1(a331fcc0f6705db836b4333ae28ff75296b6cf0d) ) /* No support for Deuces Wild sets */
 	ROM_LOAD( "mbo-cg834.u74",   0x10000, 0x8000, CRC(3e0d931a) SHA1(4796147b7e65fdb8452663db1233ef9889614a00) )
 	ROM_LOAD( "mxo-cg834.u75",   0x18000, 0x8000, CRC(2826f2d4) SHA1(4a3b0a90e030e7e9bbc927a2ec2b71bd958d6cf3) )
 
@@ -3134,7 +3134,7 @@ PayTable   3K   STR  FL  FH  4K  SF  5K  RF  4D  RF  (Bonus)
   % Range: 90.8-92.8%  Optimum: 94.8%  Hit Frequency: 45.1%
      Programs Available: PP0055, X000055P, PP0723
 */
-	ROM_REGION( 0x10000, "maincpu", 0 ) /*  10/23/95   @IGT  L95-2432  */
+	ROM_REGION( 0x10000, "maincpu", 0 )
 	ROM_LOAD( "pp0055_a47-a76.u68",   0x00000, 0x10000, CRC(adff06ea) SHA1(098409bd4474a69217e3cd17ee8c650005cc3e17) ) /* Game Version: A47, Library Version: A76 - 10/23/95   @ IGT  L95-2432  */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
@@ -3156,7 +3156,7 @@ PayTable   3K   STR  FL  FH  4K  SF  5K  RF  4D  RF  (Bonus)
   % Range: 90.8-92.8%  Optimum: 94.8%  Hit Frequency: 45.1%
      Programs Available: PP0055, X000055P, PP0723
 */
-	ROM_REGION( 0x10000, "maincpu", 0 ) /*  10/23/95   @IGT  L95-2432  */
+	ROM_REGION( 0x10000, "maincpu", 0 )
 	ROM_LOAD( "pp0055_a47-a76.u68",   0x00000, 0x10000, CRC(adff06ea) SHA1(098409bd4474a69217e3cd17ee8c650005cc3e17) ) /* Game Version: A47, Library Version: A76 - 10/23/95   @ IGT  L95-2432  */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
@@ -3272,13 +3272,13 @@ PayTable   3K   STR  FL  FH  4K  SF  5K  RF  4D  RF  (Bonus)
 	ROM_RELOAD(                       0x08000, 0x8000) /* 32K version built using earlier gaming libraries */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
-	ROM_LOAD( "mro-cg914.u72",   0x00000, 0x8000, CRC(3a428484) SHA1(04ca1148b29df394d948b5d9ae06ac0ba9e53246) ) /* Custom El Cortez card backs - 4/2/90   @ IGT  L90-0708  */
-	ROM_LOAD( "mgo-cg914.u73",   0x08000, 0x8000, CRC(dee10fa3) SHA1(2f2fc6496374e3c145f61f94da99a7c6d7ba8524) )
-	ROM_LOAD( "mbo-cg914.u74",   0x10000, 0x8000, CRC(8c05106f) SHA1(942183094df0ea6666725386711e7b60e16d3d50) )
-	ROM_LOAD( "mxo-cg914.u75",   0x18000, 0x8000, CRC(7e8453e0) SHA1(0d2fdd11767d9982657a75c1276aa8c35abfa653) )
+	ROM_LOAD( "mro-cg845.u72",   0x00000, 0x8000, CRC(af626808) SHA1(694182ae8e7d8bb3d219cc4a83672a35e489c5ea) ) /* Custom El Cortez card backs - 05/19/89   @ IGT  L89-0967  */
+	ROM_LOAD( "mgo-cg845.u73",   0x08000, 0x8000, CRC(f8aebcd1) SHA1(d4abf044bf75359ba020a6c68245351a1d191990) )
+	ROM_LOAD( "mbo-cg845.u74",   0x10000, 0x8000, CRC(01b5f798) SHA1(1b2c679f4a393d1d649421b6a08c0222a6a626f6) )
+	ROM_LOAD( "mxo-cg845.u75",   0x18000, 0x8000, CRC(e05456bd) SHA1(401652f690dae02180da4d45121823d2dc2d247f) )
 
 	ROM_REGION( 0x100, "proms", 0 )
-	ROM_LOAD( "cap914.u50", 0x0000, 0x0100, CRC(ab8ec1e4) SHA1(e2af88f4ff555a8d56fef98adb57149522239a07) )
+	ROM_LOAD( "cap845.u50", 0x0000, 0x0100, CRC(00439b0d) SHA1(4367ebf3eb90322d796f082f52da2667b0766c1e) )
 ROM_END
 
 ROM_START( pepp0057c ) /* Normal board : Deuces Wild Poker (PP0057) */
@@ -3379,7 +3379,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
      Programs Available: PP0060, X000060P & PP0420 - Non Double-up Only
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0060_a45-a74.u68",   0x00000, 0x10000, CRC(5d9e6c2f) SHA1(e1199a1fa57d84223ca87ea5b6ce4fda9afa0e1f) ) /* Game Version: A45, Library Version: A74 */
+	ROM_LOAD( "pp0060_a45-a74.u68",   0x00000, 0x10000, CRC(5d9e6c2f) SHA1(e1199a1fa57d84223ca87ea5b6ce4fda9afa0e1f) ) /* Game Version: A45, Library Version: A74 - 10/23/95   @ IGT  L95-2259 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2004.u72",  0x00000, 0x8000, CRC(e5e40ea5) SHA1(e0d9e50b30cc0c25c932b2bf444990df1fb2c38c) ) /*  08/31/94   @ IGT  L95-0146  */
@@ -3445,7 +3445,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 NOTE: PSR for build A6H-A8H shows CG2004 with CAP740, but found with CG2002 - All chips labaled CRUIS
 
 */
-	ROM_REGION( 0x10000, "maincpu", 0 ) /*  11/13/97   @IGT  CRUIS  */
+	ROM_REGION( 0x10000, "maincpu", 0 )
 	ROM_LOAD( "pp0060_a6h-a8h.u68",   0x00000, 0x10000, CRC(81963084) SHA1(2493bb040b9d0ea5cfe77f8d07546d3a3ac3716a) ) /* Game Version: A6H, Library Version: A8H - 11/13/97   IGT CRUIS */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
@@ -3778,10 +3778,10 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 	ROM_RELOAD(                       0x08000, 0x8000) /* 32K version built using earlier gaming libraries */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
-	ROM_LOAD( "mro-cg864.u72",   0x00000, 0x8000, CRC(f4ac28b9) SHA1(35c8a603120f35bd92905e0491e9ae5cd201e13f) ) /*  09/13/89   @ IGT  L89-1706  */
-	ROM_LOAD( "mgo-cg864.u73",   0x08000, 0x8000, CRC(da8efcb9) SHA1(942c6b613074c52f6ed1c2fce78d46ef0f221c48) ) /* Custom Mirage casino card backs */
-	ROM_LOAD( "mbo-cg864.u74",   0x10000, 0x8000, CRC(d48ac9cd) SHA1(a62d6c1daf199856aa1777d1d99fe81399215e36) ) /* These graphics will work for many other standard poker sets */
-	ROM_LOAD( "mxo-cg864.u75",   0x18000, 0x8000, CRC(04f81245) SHA1(055271c6c502fad3be5f2d694a94f96bf3176404) ) /* However there is no support for Deuces Wild sets */
+	ROM_LOAD( "mro-cg864.u72",   0x00000, 0x8000, CRC(f4ac28b9) SHA1(35c8a603120f35bd92905e0491e9ae5cd201e13f) ) /* Custom Mirage casino - 09/13/89   @ IGT  L89-1706  */
+	ROM_LOAD( "mgo-cg864.u73",   0x08000, 0x8000, CRC(da8efcb9) SHA1(942c6b613074c52f6ed1c2fce78d46ef0f221c48) ) /* No support for Deuces Wild sets */
+	ROM_LOAD( "mbo-cg864.u74",   0x10000, 0x8000, CRC(d48ac9cd) SHA1(a62d6c1daf199856aa1777d1d99fe81399215e36) )
+	ROM_LOAD( "mxo-cg864.u75",   0x18000, 0x8000, CRC(04f81245) SHA1(055271c6c502fad3be5f2d694a94f96bf3176404) )
 
 	ROM_REGION( 0x100, "proms", 0 )
 	ROM_LOAD( "cap864.u50", 0x0000, 0x0100, CRC(c80e5743) SHA1(edf4e5a68905cc566077613d856bc90b8136a227) )
@@ -3962,10 +3962,10 @@ PayTable   3K   STR  FL  FH  4K  SF  5K   RF    4D   RF   4D  (Bonus)
 	ROM_LOAD( "pp0127_611-597.u68",   0x00000, 0x10000, CRC(90e94e05) SHA1(d0d368b2c51ccf5c7dbaa4763db08260f0802c32) ) /* Game Version: 611, Library Version: 597 - 11-21-89   @ IGT  L89-1415  */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
-	ROM_LOAD( "mro-cg1348.u72",  0x00000, 0x8000, CRC(b2411211) SHA1(fb78da8c92be7b0ce174aecd0392875fdd3653e7) )
-	ROM_LOAD( "mgo-cg1348.u73",  0x08000, 0x8000, CRC(06e97f8a) SHA1(bcdd33aa36746d71fb6ce804eb222ecd7b27d0d6) )
-	ROM_LOAD( "mbo-cg1348.u74",  0x10000, 0x8000, CRC(5a4547fd) SHA1(ec28731253733b4ecdff341120ae8572995cffc6) )
-	ROM_LOAD( "mxo-cg1348.u75",  0x18000, 0x8000, CRC(cdd8485f) SHA1(4af2f270ed40955bb11f0e427f4ad614fcb3157c) )
+	ROM_LOAD( "mro-cg773.u72",   0x00000, 0x8000, CRC(73827e49) SHA1(f2b3f58aeac62b36ba60a408cf04c691b0564ace) ) /*  10-06-88   @ IGT  L88-2023  */
+	ROM_LOAD( "mgo-cg773.u73",   0x08000, 0x8000, CRC(af569952) SHA1(d28ae1c216a99bedc4315e61151934f53b932ef4) )
+	ROM_LOAD( "mbo-cg773.u74",   0x10000, 0x8000, CRC(3b59799b) SHA1(b6da6e719f5cc475f2f7112d6a8fe346ea5d511e) )
+	ROM_LOAD( "mxo-cg773.u75",   0x18000, 0x8000, CRC(75da0cd8) SHA1(4fb4eda9ae8e59884201368c7d8e4ff8b9967a4f) )
 
 	ROM_REGION( 0x100, "proms", 0 )
 	ROM_LOAD( "cap773.u50", 0x0000, 0x0100, CRC(294b7b10) SHA1(a405a4b8547b713c5c02dacb19e7354095a7b584) )
@@ -3994,7 +3994,7 @@ PayTable   3K   STR  FL  FH  4K  SF  5K   RF    4D   RF   4D  (Bonus)
 	ROM_LOAD( "cap773.u50", 0x0000, 0x0100, CRC(294b7b10) SHA1(a405a4b8547b713c5c02dacb19e7354095a7b584) )
 ROM_END
 
-ROM_START( pepp0129 ) /* Normal board : Joker Poker (Two Pair or Better) (PP0129) */
+ROM_START( pepp0129 ) /* Normal board : Joker Poker (Two Pair or Better) (PP0129) - Tournament Mode capable */
 /*
                                        w/J     w/oJ
 PayTable   2P  3K  STR  FL  FH  4K  SF  RF  5K  RF  (Bonus)
@@ -4028,7 +4028,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
      Programs Available: PP0130
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0130_a4y-a6g.u68",   0x00000, 0x10000, CRC(bf9293f2) SHA1(79f5247a2d5447c89e281c618b09c7f7790176a2) ) /* Game Version: A4Y, Library Version: A6G - 09/09/96   IGT  L96-2634 */
+	ROM_LOAD( "pp0130_a4y-a6g.u68",   0x00000, 0x10000, CRC(bf9293f2) SHA1(79f5247a2d5447c89e281c618b09c7f7790176a2) ) /* Game Version: A4Y, Library Version: A6G - 09/09/96   @ IGT  L96-2634 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2135.u72",  0x00000, 0x8000, CRC(ecb5c319) SHA1(8c6dce009017c919b4ebfeb0292cfb8819b652a0) ) /*  02/08/95   @ IGT  MS  */
@@ -4050,10 +4050,10 @@ PayTable   Js+  2PR  3K  STR  FL  FH  4K  SF  RF  (Bonus)
      Programs Available: PP0132, PP0447, X000447P
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0132_896-914.u68",   0x00000, 0x10000, CRC(ad888692) SHA1(cbc78c546b8f4dc136cc376a0b7aed10faacbac6) ) /* Game Version: 896, Library Version: 914 */
+	ROM_LOAD( "pp0132_896-914.u68",   0x00000, 0x10000, CRC(ad888692) SHA1(cbc78c546b8f4dc136cc376a0b7aed10faacbac6) ) /* Game Version: 896, Library Version: 914 - 05/11/93   IGT  IL */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
-	ROM_LOAD( "mro-cg2002.u72",  0x00000, 0x8000, CRC(d9d03979) SHA1(9729cbb2e5472eb652f8f549dd85047abe11cae0) ) /* 08/30/94   @IGT  */
+	ROM_LOAD( "mro-cg2002.u72",  0x00000, 0x8000, CRC(d9d03979) SHA1(9729cbb2e5472eb652f8f549dd85047abe11cae0) ) /* 08/30/94   @IGT  CRUIS */
 	ROM_LOAD( "mgo-cg2002.u73",  0x08000, 0x8000, CRC(ad5bd2cd) SHA1(e5dacd2827f14dd9811311552b7e3816a36b9284) )
 	ROM_LOAD( "mbo-cg2002.u74",  0x10000, 0x8000, CRC(7362f7f3) SHA1(fce4ce2cdd836e37382d39d8b167019cfc4c6166) )
 	ROM_LOAD( "mxo-cg2002.u75",  0x18000, 0x8000, CRC(4560fdec) SHA1(63ec67afd378a06d74084bba72fbbe9be12e24d3) )
@@ -4071,7 +4071,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
      Programs Available: PP0150, X000150P
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0150_a45-a74.u68",   0x00000, 0x10000, CRC(8848dc4b) SHA1(121e885d253aa3c2a72de9e14d64e20d794e53bf) ) /* Game Version: A45, Library Version: A74 */
+	ROM_LOAD( "pp0150_a45-a74.u68",   0x00000, 0x10000, CRC(8848dc4b) SHA1(121e885d253aa3c2a72de9e14d64e20d794e53bf) ) /* Game Version: A45, Library Version: A74 - 11/13/95   @ IGT  L95-2463 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2004.u72",  0x00000, 0x8000, CRC(e5e40ea5) SHA1(e0d9e50b30cc0c25c932b2bf444990df1fb2c38c) ) /*  08/31/94   @ IGT  L95-0146  */
@@ -4083,7 +4083,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 	ROM_LOAD( "cap740.u50", 0x0000, 0x0100, CRC(6fe619c4) SHA1(49e43dafd010ce0fe9b2a63b96a4ddedcb933c6d) )
 ROM_END
 
-ROM_START( pepp0158 ) /* Normal board : 4 of a Kind Bonus Poker (PP0158) - 03/17/97   @ IGT  L97-0628 - Tournament Mode capable - PSR Verified */
+ROM_START( pepp0158 ) /* Normal board : 4 of a Kind Bonus Poker (PP0158) - Tournament Mode capable - PSR Verified */
 /*
                                        5-K 2-4
 PayTable   Js+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
@@ -4093,7 +4093,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
      Programs Available: PP0158, X000158P
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0158_a67-a8k.u68",   0x00000, 0x10000, CRC(715aeadf) SHA1(e90b1f0a1d4886882c9259d84c950076f9fd521d) ) /* Game Version: A67, Library Version: A8K */
+	ROM_LOAD( "pp0158_a67-a8k.u68",   0x00000, 0x10000, CRC(715aeadf) SHA1(e90b1f0a1d4886882c9259d84c950076f9fd521d) ) /* Game Version: A67, Library Version: A8K - 03/17/97   @ IGT  L97-0628  */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2108.u72",   0x00000, 0x8000, CRC(4d2d2223) SHA1(4672d4302697cfa2e6d826f79cc3fa1bdfbd8315) ) /*  11/29/94   @ IGT  L94-2198  */
@@ -4105,7 +4105,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
 	ROM_LOAD( "cap740.u50", 0x0000, 0x0100, CRC(6fe619c4) SHA1(49e43dafd010ce0fe9b2a63b96a4ddedcb933c6d) )
 ROM_END
 
-ROM_START( pepp0158a ) /* Normal board : 4 of a Kind Bonus Poker (PP0158) - 10/23/95   @ IGT  L95-2438 */
+ROM_START( pepp0158a ) /* Normal board : 4 of a Kind Bonus Poker (PP0158) */
 /*
                                        5-K 2-4
 PayTable   Js+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
@@ -4115,22 +4115,21 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
      Programs Available: PP0158, X000158P
 
 NOTE: As found but PSR for build A46-A75 shows CG2003 with CAP904
-
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0158_a46-a75.u68",   0x00000, 0x10000, CRC(5976cd19) SHA1(6a461ea9ddf78dffa3cf8b65903ebf3127f23d45) ) /* Game Version: A46, Library Version: A75, Video Lib ver A0Y */
+	ROM_LOAD( "pp0158_a46-a75.u68",   0x00000, 0x10000, CRC(5976cd19) SHA1(6a461ea9ddf78dffa3cf8b65903ebf3127f23d45) ) /* Game Version: A46, Library Version: A75, Video Lib ver A0Y - 10/23/95   @ IGT  L95-2438 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg1047.u72",  0x00000, 0x8000, CRC(a299d058) SHA1(ed090bacac07c4cf85eacc80f15489b4c18b33d3) ) /* Custom Skyline Casino card backs */
-	ROM_LOAD( "mgo-cg1047.u73",  0x08000, 0x8000, CRC(d9aa8951) SHA1(c42a256368871a38ceaca8b66256e235dbe2adad) )
-	ROM_LOAD( "mbo-cg1047.u74",  0x10000, 0x8000, CRC(5051fb59) SHA1(159559d6e40287e34b1538c51e779d22b910710d) ) /* These graphics will work for many other standard poker sets */
-	ROM_LOAD( "mxo-cg1047.u75",  0x18000, 0x8000, CRC(2f86cf5a) SHA1(0a271f3d2353303fbab80c61fec8e2dda877c42b) ) /* For Deuces Wild sets use CG1276 + CAP1276 */
+	ROM_LOAD( "mgo-cg1047.u73",  0x08000, 0x8000, CRC(d9aa8951) SHA1(c42a256368871a38ceaca8b66256e235dbe2adad) ) /* For Deuces Wild sets use CG1276 + CAP1276 */
+	ROM_LOAD( "mbo-cg1047.u74",  0x10000, 0x8000, CRC(5051fb59) SHA1(159559d6e40287e34b1538c51e779d22b910710d) )
+	ROM_LOAD( "mxo-cg1047.u75",  0x18000, 0x8000, CRC(2f86cf5a) SHA1(0a271f3d2353303fbab80c61fec8e2dda877c42b) )
 
 	ROM_REGION( 0x100, "proms", 0 )
-	ROM_LOAD( "cap1046.u50", 0x0000, 0x0100, CRC(883fa6a4) SHA1(76aa42912d3180dc0466be95f30d6d760996713b) ) /* Uses CAP1046 as stated or really CAP1047?? */
+	ROM_LOAD( "cap1046.u50", 0x0000, 0x0100, CRC(883fa6a4) SHA1(76aa42912d3180dc0466be95f30d6d760996713b) )
 ROM_END
 
-ROM_START( pepp0158b ) /* Normal board : 4 of a Kind Bonus Poker (PP0158) - 04/16/94   @ IGT  L94-1044 - PSR Verified */
+ROM_START( pepp0158b ) /* Normal board : 4 of a Kind Bonus Poker (PP0158) - PSR Verified */
 /*
                                        5-K 2-4
 PayTable   Js+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
@@ -4140,7 +4139,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
      Programs Available: PP0158, X000158P
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0158_a0n-a23.u68",   0x00000, 0x10000, CRC(f3f9b6da) SHA1(1aedcb5257890c52c633357f8b96e72fe51158f8) ) /* Game Version: A0N, Library Version: A23, Video Lib ver A0Y */
+	ROM_LOAD( "pp0158_a0n-a23.u68",   0x00000, 0x10000, CRC(f3f9b6da) SHA1(1aedcb5257890c52c633357f8b96e72fe51158f8) ) /* Game Version: A0N, Library Version: A23, Video Lib ver A0Y - 04/16/94   @ IGT  L94-1044  */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2003.u72",  0x00000, 0x8000, CRC(0d425f48) SHA1(b60aaf3f4bd76f75f72f6e8dda724bdf795cb521) ) /*  08/30/94   @ IGT  L95-0145  */
@@ -4186,7 +4185,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
 NOTE: While this is a 32K version, it does require DOOR OPEN cycling and isn't compatible with earlier non-plus boards
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0158_631-607.u68",   0x00000, 0x8000, CRC(5fe3498c) SHA1(f1405bf016d46904228cda88d8d94e2a956b2347) ) /* Game Version: 631, Library Version: 607, Video Lib Ver: 607 */
+	ROM_LOAD( "pp0158_631-607.u68",   0x00000, 0x8000, CRC(5fe3498c) SHA1(f1405bf016d46904228cda88d8d94e2a956b2347) ) /* Game Version: 631, Library Version: 607, Video Lib Ver: 607 - 02-14-90   @ IGT  L90-0707 */
 	ROM_RELOAD(                       0x08000, 0x8000) /* 32K version built using earlier gaming libraries */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
@@ -4229,8 +4228,8 @@ PayTable   Ks+  2P  3K  STR  FL  FH  4K  SF  RF  5K  RF  (Bonus)
   % Range: 92.4-94.4%  Optimum: 96.4%  Hit Frequency: 44.2%
      Programs Available: PP0171, X000171P
 */
-	ROM_REGION( 0x10000, "maincpu", 0 ) /*  10/23/95   @IGT  L95-2281  */
-	ROM_LOAD( "pp0171_a45-a74.u68",   0x00000, 0x10000, CRC(7a68ee4b) SHA1(298ca0c87229929b61ddfdf8c0bac82e9df17e83) ) /* Game Version: A45, Library Version: A74 */
+	ROM_REGION( 0x10000, "maincpu", 0 )
+	ROM_LOAD( "pp0171_a45-a74.u68",   0x00000, 0x10000, CRC(7a68ee4b) SHA1(298ca0c87229929b61ddfdf8c0bac82e9df17e83) ) /* Game Version: A45, Library Version: A74 - 10/23/95   @ IGT  L95-2281 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2004.u72",  0x00000, 0x8000, CRC(e5e40ea5) SHA1(e0d9e50b30cc0c25c932b2bf444990df1fb2c38c) ) /*  08/31/94   @ IGT  L95-0146  */
@@ -4251,7 +4250,7 @@ PayTable   Ks+  2P  3K  STR  FL  FH  4K  SF  RF  5K  RF  (Bonus)
   % Range: 92.4-94.4%  Optimum: 96.4%  Hit Frequency: 44.2%
      Programs Available: PP0171, X000171P
 */
-	ROM_REGION( 0x10000, "maincpu", 0 ) /*  10/23/95   @IGT  L95-2281  */
+	ROM_REGION( 0x10000, "maincpu", 0 )
 	ROM_LOAD( "pp0171_a2e-a49.u68",   0x00000, 0x10000, CRC(efd6a33a) SHA1(72f5a4c9923f46a59a61b3b034b1275ebfeadac6) ) /* Game Version: A2E, Library Version: A49 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
@@ -4297,7 +4296,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
      Programs Available: PP0181
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0181_648-667.u68",   0x00000, 0x10000, CRC(b38ff1e1) SHA1(ae8d725a3352000c57cef4b7e7a39dbad940e9de) ) /* Game Version: 648, Library Version: 667 */
+	ROM_LOAD( "pp0181_648-667.u68",   0x00000, 0x10000, CRC(b38ff1e1) SHA1(ae8d725a3352000c57cef4b7e7a39dbad940e9de) ) /* Game Version: 648, Library Version: 667 - 08/28/90   @ IGT  L90-1473 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg740.u72",   0x00000, 0x8000, CRC(72667f6c) SHA1(89843f472cc0329317cfc643c63bdfd11234b194) ) /*  08/12/87   @ IGT  L87-2243  */
@@ -4309,7 +4308,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 	ROM_LOAD( "cap740.u50", 0x0000, 0x0100, CRC(6fe619c4) SHA1(49e43dafd010ce0fe9b2a63b96a4ddedcb933c6d) )
 ROM_END
 
-ROM_START( pepp0188 ) /* Normal board : Standard Draw Poker (PP0188) */
+ROM_START( pepp0188 ) /* Normal board : Standard Draw Poker (PP0188) - Tournament Mode capable */
 /*
 PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 ----------------------------------------------------------
@@ -4321,10 +4320,10 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 	ROM_LOAD( "pp0188_986-a0u.u68",   0x00000, 0x10000, CRC(cf36a53c) SHA1(99b578538ab24d9ff91971b1f77599272d1dbfc6) ) /* Game Version: 986, Library Version: A0U */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
-	ROM_LOAD( "mro-cg740.u72",   0x00000, 0x8000, CRC(72667f6c) SHA1(89843f472cc0329317cfc643c63bdfd11234b194) ) /*  08/12/87   @ IGT  L87-2243  */
-	ROM_LOAD( "mgo-cg740.u73",   0x08000, 0x8000, CRC(7437254a) SHA1(bba166dece8af58da217796f81117d0b05752b87) )
-	ROM_LOAD( "mbo-cg740.u74",   0x10000, 0x8000, CRC(92e8c33e) SHA1(05344664d6fdd3f4205c50fa4ca76fc46c18cf8f) )
-	ROM_LOAD( "mxo-cg740.u75",   0x18000, 0x8000, CRC(ce4cbe0b) SHA1(4bafcd68be94a5deaae9661584fa0fc940b834bb) )
+	ROM_LOAD( "mro-cg2004.u72",  0x00000, 0x8000, CRC(e5e40ea5) SHA1(e0d9e50b30cc0c25c932b2bf444990df1fb2c38c) ) /*  08/31/94   @ IGT  L95-0146  */
+	ROM_LOAD( "mgo-cg2004.u73",  0x08000, 0x8000, CRC(12607f1e) SHA1(248e1ecee4e735f5943c50f8c350ca95b81509a7) )
+	ROM_LOAD( "mbo-cg2004.u74",  0x10000, 0x8000, CRC(78c3fb9f) SHA1(2b9847c511888de507a008dec981778ca4dbcd6c) )
+	ROM_LOAD( "mxo-cg2004.u75",  0x18000, 0x8000, CRC(5aaa4480) SHA1(353c4ce566c944406fce21f2c5045c856ef7a609) )
 
 	ROM_REGION( 0x100, "proms", 0 )
 	ROM_LOAD( "cap740.u50", 0x0000, 0x0100, CRC(6fe619c4) SHA1(49e43dafd010ce0fe9b2a63b96a4ddedcb933c6d) )
@@ -4393,7 +4392,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 	ROM_LOAD( "cap740.u50", 0x0000, 0x0100, CRC(6fe619c4) SHA1(49e43dafd010ce0fe9b2a63b96a4ddedcb933c6d) )
 ROM_END
 
-ROM_START( pepp0190 ) /* Normal board : Deuces Wild Poker (No Double-up) (PP0190) - PSR Verified */
+ROM_START( pepp0190 ) /* Normal board : Deuces Wild Poker (PP0190) - PSR Verified */
 /*
                                         w/D     w/oD
 PayTable   3K   STR  FL  FH  4K  SF  5K  RF  4D  RF  (Bonus)
@@ -4401,8 +4400,6 @@ PayTable   3K   STR  FL  FH  4K  SF  5K  RF  4D  RF  (Bonus)
   P57A      1    2    3   4   4   8  10  20 200 250    800
   % Range: 92.0-94.0%  Optimum: 96.0%  Hit Frequency: 44.5%
      Programs Available: PP0417, X000417P, X000190P & PP0190 - Non Double-up Only
-
-NOTE: This later build works with CG1215 (and later Deuces Wild) graphics roms and is NOT compatible with CG773
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
 	ROM_LOAD( "pp0190_a47-a76.u68",   0x00000, 0x10000, CRC(974f9d7a) SHA1(8fe65c568246fbf97b20cd2b05cccb23022dff65) ) /* Game Version: A47, Library Version: A76 - 11/13/95   @ IGT  L99-0100  */
@@ -4417,7 +4414,7 @@ NOTE: This later build works with CG1215 (and later Deuces Wild) graphics roms a
 	ROM_LOAD( "cap773.u50", 0x0000, 0x0100, CRC(294b7b10) SHA1(a405a4b8547b713c5c02dacb19e7354095a7b584) )
 ROM_END
 
-ROM_START( pepp0190a ) /* Normal board : Deuces Wild Poker (No Double-up) (PP0190) - requires SET001 chip to set denomination - PSR Verified */
+ROM_START( pepp0190a ) /* Normal board : Deuces Wild Poker (PP0190) - requires SET001 chip to set denomination - PSR Verified */
 /*
                                         w/D     w/oD
 PayTable   3K   STR  FL  FH  4K  SF  5K  RF  4D  RF  (Bonus)
@@ -4445,7 +4442,7 @@ Internally the program erroneously reports a 94.00% return.
 	ROM_LOAD( "cap773.u50", 0x0000, 0x0100, CRC(294b7b10) SHA1(a405a4b8547b713c5c02dacb19e7354095a7b584) )
 ROM_END
 
-ROM_START( pepp0190b ) /* Normal board : Deuces Wild Poker (No Double-up) (PP0190) */
+ROM_START( pepp0190b ) /* Normal board : Deuces Wild Poker (PP0190) */
 /*
                                         w/D     w/oD
 PayTable   3K   STR  FL  FH  4K  SF  5K  RF  4D  RF  (Bonus)
@@ -4511,7 +4508,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
 	ROM_LOAD( "cap904.u50", 0x0000, 0x0100, CRC(0eec8336) SHA1(a6585c978dbc2f4f3818e3a5b92f8c28be23c4c0) )
 ROM_END
 
-ROM_START( pepp0197 ) /* Normal board : Standard Draw Poker (PP0197) - 10/23/95   @ IGT  L95-2452 - PSR Verified */
+ROM_START( pepp0197 ) /* Normal board : Standard Draw Poker (PP0197)- PSR Verified */
 /*
 PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 ----------------------------------------------------------
@@ -4520,7 +4517,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
      Programs Available: PP0197, X000197P & PP0419 - Non Double-up Only
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0197_a45-a75.u68",   0x00000, 0x10000, CRC(6b5b3108) SHA1(2fafcf979db92d4f9f1fb0a2e9645fd71d8dd5c2) ) /* Game Version: A45, Library Version: A75 */
+	ROM_LOAD( "pp0197_a45-a75.u68",   0x00000, 0x10000, CRC(6b5b3108) SHA1(2fafcf979db92d4f9f1fb0a2e9645fd71d8dd5c2) ) /* Game Version: A45, Library Version: A75 - 10/23/95   @ IGT  L95-2452  */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2004.u72",  0x00000, 0x8000, CRC(e5e40ea5) SHA1(e0d9e50b30cc0c25c932b2bf444990df1fb2c38c) ) /*  08/31/94   @ IGT  L95-0146  */
@@ -4532,7 +4529,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 	ROM_LOAD( "cap740.u50", 0x0000, 0x0100, CRC(6fe619c4) SHA1(49e43dafd010ce0fe9b2a63b96a4ddedcb933c6d) )
 ROM_END
 
-ROM_START( pepp0197a ) /* Normal board : Standard Draw Poker (PP0197) - 07/29/96   @ IGT  L96-1219 - PSR Verified */
+ROM_START( pepp0197a ) /* Normal board : Standard Draw Poker (PP0197) - PSR Verified */
 /*
 PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 ----------------------------------------------------------
@@ -4541,7 +4538,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
      Programs Available: PP0197, X000197P & PP0419 - Non Double-up Only
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0197_a14-a2n.u68",   0x00000, 0x10000, CRC(ef472672) SHA1(785ce02b13894e5cb7575e75533451b96e3f4e6d) ) /* Game Version: A14, Library Version: A2N */
+	ROM_LOAD( "pp0197_a14-a2n.u68",   0x00000, 0x10000, CRC(ef472672) SHA1(785ce02b13894e5cb7575e75533451b96e3f4e6d) ) /* Game Version: A14, Library Version: A2N - 07/29/96   @ IGT  L96-1219 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2004.u72",  0x00000, 0x8000, CRC(e5e40ea5) SHA1(e0d9e50b30cc0c25c932b2bf444990df1fb2c38c) ) /*  08/31/94   @ IGT  L95-0146  */
@@ -4562,7 +4559,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
      Programs Available: PP0197, X000197P & PP0419 - Non Double-up Only
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0197_979-a0c.u68",   0x00000, 0x10000, CRC(ae817534) SHA1(b2454609e8275aab00797966c0f4e68eae2911cd) ) /* Game Version: 979, Library Version: A0C */
+	ROM_LOAD( "pp0197_979-a0c.u68",   0x00000, 0x10000, CRC(ae817534) SHA1(b2454609e8275aab00797966c0f4e68eae2911cd) ) /* Game Version: 979, Library Version: A0C - 04/14/94   @ IGT  MS */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2004.u72",  0x00000, 0x8000, CRC(e5e40ea5) SHA1(e0d9e50b30cc0c25c932b2bf444990df1fb2c38c) ) /*  08/31/94   @ IGT  L95-0146  */
@@ -4595,7 +4592,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 	ROM_LOAD( "cap740.u50", 0x0000, 0x0100, CRC(6fe619c4) SHA1(49e43dafd010ce0fe9b2a63b96a4ddedcb933c6d) )
 ROM_END
 
-ROM_START( pepp0197d ) /* Normal board : Standard Draw Poker (Auto Hold in options) (PP0197) */
+ROM_START( pepp0197d ) /* Normal board : Standard Draw Poker (PP0197) */
 /*
 PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 ----------------------------------------------------------
@@ -4626,7 +4623,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
      Programs Available: PP0197, X000197P & PP0419 - Non Double-up Only
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0197_a6h-a8h.u68",   0x00000, 0x10000, CRC(c8825e06) SHA1(a26607b0aa4f76371a0b9d3fdd069e8ada204daf) ) /* Game Version: A6H, Library Version: A8H - 11/13/97   IGT  L97-2583 */
+	ROM_LOAD( "pp0197_a6h-a8h.u68",   0x00000, 0x10000, CRC(c8825e06) SHA1(a26607b0aa4f76371a0b9d3fdd069e8ada204daf) ) /* Game Version: A6H, Library Version: A8H - 11/13/97   @ IGT  L97-2583 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2004.u72",  0x00000, 0x8000, CRC(e5e40ea5) SHA1(e0d9e50b30cc0c25c932b2bf444990df1fb2c38c) ) /*  08/31/94   @ IGT  L95-0146  */
@@ -4638,7 +4635,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 	ROM_LOAD( "cap740.u50", 0x0000, 0x0100, CRC(6fe619c4) SHA1(49e43dafd010ce0fe9b2a63b96a4ddedcb933c6d) )
 ROM_END
 
-ROM_START( pepp0203 ) /* Normal board : 4 of a Kind Bonus Poker (PP0203) - 10/23/95   @ IGT  L95-2446 - PSR Verified */
+ROM_START( pepp0203 ) /* Normal board : 4 of a Kind Bonus Poker (PP0203) - PSR Verified */
 /*
                                        5-K 2-4
 PayTable   Js+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
@@ -4648,7 +4645,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
      Programs Available: PP0203, X000203P, PP0590 & PP0409 - Non Double-up Only
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0203_a46-a75.u68",   0x00000, 0x10000, CRC(2955eeb5) SHA1(ac2483dbb92de84ab64d0d7e55acff196966ea1b) ) /* Game Version: A46, Library Version: A75, Video Lib ver: A0Y - 10/23/95   IGT  L95-2446 */
+	ROM_LOAD( "pp0203_a46-a75.u68",   0x00000, 0x10000, CRC(2955eeb5) SHA1(ac2483dbb92de84ab64d0d7e55acff196966ea1b) ) /* Game Version: A46, Library Version: A75, Video Lib ver: A0Y - 10/23/95   @ IGT  L95-2446 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2003.u72",  0x00000, 0x8000, CRC(0d425f48) SHA1(b60aaf3f4bd76f75f72f6e8dda724bdf795cb521) ) /*  08/30/94   @ IGT  L95-0145  */
@@ -4670,7 +4667,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
      Programs Available: PP0203, X000203P, PP0590 & PP0409 - Non Double-up Only
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0203_a0n-a23.u68",   0x00000, 0x10000, CRC(fce4ea36) SHA1(4c1be0cb3600bbcac768b942f7b8bddd5d626ef6) ) /* Game Version: A0N, Library Version: A23, Video Lib ver: A0Y - 04/16/94   IGT  L94-1048 */
+	ROM_LOAD( "pp0203_a0n-a23.u68",   0x00000, 0x10000, CRC(fce4ea36) SHA1(4c1be0cb3600bbcac768b942f7b8bddd5d626ef6) ) /* Game Version: A0N, Library Version: A23, Video Lib ver: A0Y - 04/16/94   @ IGT  L94-1048 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2003.u72",  0x00000, 0x8000, CRC(0d425f48) SHA1(b60aaf3f4bd76f75f72f6e8dda724bdf795cb521) ) /*  08/30/94   @ IGT  L95-0145  */
@@ -4693,7 +4690,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
      Programs Available: PP0203, X000203P, PP0590 & PP0409 - Non Double-up Only
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0203_989-974.u68",   0x00000, 0x10000, CRC(15b6b464) SHA1(672d9e198d00bfc7d444957d31b8f8de7ba48ca0) ) /* Game Version: 989, Library Version: 974, Video Lib ver: A0Y - 12/20/93   IGT  L94-0037 */
+	ROM_LOAD( "pp0203_989-974.u68",   0x00000, 0x10000, CRC(15b6b464) SHA1(672d9e198d00bfc7d444957d31b8f8de7ba48ca0) ) /* Game Version: 989, Library Version: 974, Video Lib ver: A0Y - 12/20/93   @ IGT  L94-0037 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2003.u72",  0x00000, 0x8000, CRC(0d425f48) SHA1(b60aaf3f4bd76f75f72f6e8dda724bdf795cb521) ) /*  08/30/94   @ IGT  L95-0145  */
@@ -4761,7 +4758,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
 NOTE: While this is a 32K version, it does require DOOR OPEN cycling and isn't compatible with earlier non-plus boards
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0203_631-607.u68",   0x00000, 0x8000, CRC(ad61ee10) SHA1(477d1b17c368ea194a460e839d7de4c2a9a256a4) ) /* Game Version: 631, Library Version: 607, Video Lib Ver: 607 - 08/22/90   IGT  L90-1414 */
+	ROM_LOAD( "pp0203_631-607.u68",   0x00000, 0x8000, CRC(ad61ee10) SHA1(477d1b17c368ea194a460e839d7de4c2a9a256a4) ) /* Game Version: 631, Library Version: 607, Video Lib Ver: 607 - 08/22/90   @ IGT  L90-1414 */
 	ROM_RELOAD(                       0x08000, 0x8000) /* 32K version built using earlier gaming libraries */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
@@ -4796,7 +4793,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
 	ROM_LOAD( "cap904.u50", 0x0000, 0x0100, CRC(0eec8336) SHA1(a6585c978dbc2f4f3818e3a5b92f8c28be23c4c0) )
 ROM_END
 
-ROM_START( pepp0219 ) /* Normal board : Standard Draw Poker (Auto Hold in options) (PP0219) */
+ROM_START( pepp0219 ) /* Normal board : Standard Draw Poker (PP0219) */
 /*
 PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 ----------------------------------------------------------
@@ -4850,7 +4847,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 	ROM_LOAD( "pp0221_896-914.u68",   0x00000, 0x10000, CRC(14d50334) SHA1(281c4467f57f91d0da98242b085973c06193085a) ) /* Game Version: 896, Library Version: 914 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
-	ROM_LOAD( "mro-cg2002.u72",  0x00000, 0x8000, CRC(d9d03979) SHA1(9729cbb2e5472eb652f8f549dd85047abe11cae0) ) /* 08/30/94   @IGT  */
+	ROM_LOAD( "mro-cg2002.u72",  0x00000, 0x8000, CRC(d9d03979) SHA1(9729cbb2e5472eb652f8f549dd85047abe11cae0) ) /* 08/30/94   @IGT  CRUIS */
 	ROM_LOAD( "mgo-cg2002.u73",  0x08000, 0x8000, CRC(ad5bd2cd) SHA1(e5dacd2827f14dd9811311552b7e3816a36b9284) )
 	ROM_LOAD( "mbo-cg2002.u74",  0x10000, 0x8000, CRC(7362f7f3) SHA1(fce4ce2cdd836e37382d39d8b167019cfc4c6166) )
 	ROM_LOAD( "mxo-cg2002.u75",  0x18000, 0x8000, CRC(4560fdec) SHA1(63ec67afd378a06d74084bba72fbbe9be12e24d3) )
@@ -4859,7 +4856,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 	ROM_LOAD( "cap740.u50", 0x0000, 0x0100, CRC(6fe619c4) SHA1(49e43dafd010ce0fe9b2a63b96a4ddedcb933c6d) )
 ROM_END
 
-ROM_START( pepp0221b ) /* Normal board : Standard Draw Poker (Auto Hold in options) (PP0221) - requires SET chip to set denomination */
+ROM_START( pepp0221b ) /* Normal board : Standard Draw Poker (PP0221) - requires SET chip to set denomination */
 /*
 PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 ----------------------------------------------------------
@@ -4905,7 +4902,7 @@ Internally the program erroneously reports a 92.80% return. Superseded by PP0812
 	ROM_LOAD( "cap773.u50", 0x0000, 0x0100, CRC(294b7b10) SHA1(a405a4b8547b713c5c02dacb19e7354095a7b584) )
 ROM_END
 
-ROM_START( pepp0224 ) /* Normal board : Deuces Wild Poker (No Double-up) (PP0224) - PSR Verified */
+ROM_START( pepp0224 ) /* Normal board : Deuces Wild Poker (PP0224) - PSR Verified */
 /*
                                         w/D     w/oD
 PayTable   3K   STR  FL  FH  4K  SF  5K  RF  4D  RF  (Bonus)
@@ -4927,7 +4924,7 @@ PayTable   3K   STR  FL  FH  4K  SF  5K  RF  4D  RF  (Bonus)
 	ROM_LOAD( "cap773.u50", 0x0000, 0x0100, CRC(294b7b10) SHA1(a405a4b8547b713c5c02dacb19e7354095a7b584) )
 ROM_END
 
-ROM_START( pepp0224a ) /* Normal board : Deuces Wild Poker (No Double-up) (PP0224) - PSR Verified */
+ROM_START( pepp0224a ) /* Normal board : Deuces Wild Poker (PP0224) - PSR Verified */
 /*
                                         w/D     w/oD
 PayTable   3K   STR  FL  FH  4K  SF  5K  RF  4D  RF  (Bonus)
@@ -4976,7 +4973,7 @@ Has 5 additional cards, 10 through Ace, with a US Flag for a Suit.
 
 PayTable   Js+  TP  3K  STR  FL  FH  4K  SF   5K    RF    CRF*  SeqRF   CSeqRF*  (Bonus)
 ----------------------------------------------------------------------------------------
-   ????     1    2   2   3    5   6  15  50  1000  1300  3000    5000    10000     800
+   ????     1    2   2   3    5   6  15 100  1000  1300  3000    5000    10000     800
   % Range: ???-???%  Optimum: ???%  Hit Frequency: ???%
      Programs Available: PP0232
 
@@ -4984,7 +4981,7 @@ PayTable   Js+  TP  3K  STR  FL  FH  4K  SF   5K    RF    CRF*  SeqRF   CSeqRF*
 
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0232_717-698.u68",   0x00000, 0x10000, CRC(d6d4df92) SHA1(6bb29740658131ae7f25d68427e0c7eb7cb976b0) ) /* Game Version: 717, Library Version: 698  05/02/91   @ IGT  L91-0912  */
+	ROM_LOAD( "pp0232_717-698.u68",   0x00000, 0x10000, CRC(d6d4df92) SHA1(6bb29740658131ae7f25d68427e0c7eb7cb976b0) ) /* Game Version: 717, Library Version: 698 - 05/02/91   @ IGT  L91-0912 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg1020.u72",  0x00000, 0x8000, CRC(7f8f276e) SHA1(0c5ac270ccae56295848c8714512584b6ada2306) ) /*  03-20-91   @ IGT  L91-0912  */
@@ -4996,7 +4993,7 @@ PayTable   Js+  TP  3K  STR  FL  FH  4K  SF   5K    RF    CRF*  SeqRF   CSeqRF*
 	ROM_LOAD( "cap1020.u50", 0x0000, 0x0100, CRC(abec7425) SHA1(b52223c4b6657d04230675bac6d100c103d9386a) )
 ROM_END
 
-ROM_START( pepp0242 ) /* Normal board : Deuces Wild Poker (PP0242) - Multi Regional / Multi Currency in English / Spanish - Tournament Mode capable */
+ROM_START( pepp0242 ) /* Normal board : Deuces Wild Poker (PP0242) - Multi Regional / Multi Currency in English / Spanish - Tournament Mode capable - PSR Verified */
 /*
                                         w/D     w/oD
 PayTable   3K   STR  FL  FH  4K  SF  5K  RF  4D  RF  (Bonus)
@@ -5026,9 +5023,6 @@ PayTable   3K   STR  FL  FH  4K  SF  5K  RF  4D  RF  (Bonus)
   P129A     1    2    3   4   4  10  16  25 200 250    800
   % Range: 95.7-97.7%  Optimum: 99.7%  Hit Frequency: 44.3%
      Programs Available: PP0249
-
-Superseded by PP0469
-
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
 	ROM_LOAD( "pp0249_600-550.u68",   0x00000, 0x8000, CRC(39cab612) SHA1(6ef2e533df40d9ac331dc9e2fd3bf17187f70414) ) /* Game Version: 600, Library Version: 550, Video Lib Ver: 550 */
@@ -5051,14 +5045,12 @@ PayTable  6s-10s  Js+  2PR  3K   STR  FL  FH  4K  SF   RF  (Bonus)
   ????      1      2    3    4    6    9  12  50 200  1000  4000
   % Range: 94.3-96.3%  Optimum: 98.3%  Hit Frequency: ??.?%
      Programs Available: PP0250
-
-NOTE: Newer version with DBV support and requires newer CG2015 instead of CG1019
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
 	ROM_LOAD( "pp0250_a1l-a23.u68",   0x00000, 0x10000, CRC(ae4f1fb8) SHA1(473d1acb8549f86b9da17f9fbbceafc3a3efc6fe) ) /* Game Version: A1L, Library Version: A23 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
-	ROM_LOAD( "mro-cg2015.u72",   0x00000, 0x8000, CRC(7f73ee5c) SHA1(b6c5d423c8176555c1f32605c328ffbfcf94b656) ) /* Verified CG set for this version of PP0250 */
+	ROM_LOAD( "mro-cg2015.u72",   0x00000, 0x8000, CRC(7f73ee5c) SHA1(b6c5d423c8176555c1f32605c328ffbfcf94b656) )
 	ROM_LOAD( "mgo-cg2015.u73",   0x08000, 0x8000, CRC(de270e0e) SHA1(41b207f9380f623ab64dc42224275cccd43417ee) )
 	ROM_LOAD( "mbo-cg2015.u74",   0x10000, 0x8000, CRC(02e623d9) SHA1(4c689293f5c5a8eb0b17861cf433ae1e01d83545) )
 	ROM_LOAD( "mxo-cg2015.u75",   0x18000, 0x8000, CRC(0c96b7fc) SHA1(adde93f08db0b957daf77d57a7ab60af3b667f25) )
@@ -5074,15 +5066,13 @@ PayTable  6s-10s  Js+  2PR  3K   STR  FL  FH  4K  SF   RF  (Bonus)
   ????      1      2    3    4    6    9  12  50 200  1000  4000
   % Range: 94.3-96.3%  Optimum: 98.3%  Hit Frequency: ??.?%
      Programs Available: PP0250
-
-NOTE: No DBV option and requires CG1019
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
 	ROM_LOAD( "pp0250_733-778.u68",   0x00000, 0x10000, CRC(4c919598) SHA1(fe73503c6ccb3c5746fb96be58cd5b740c819713) ) /* Game Version: 733, Library Version: 778 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
-	ROM_LOAD( "mro-cg1019.u72",   0x00000, 0x8000, CRC(9086dc3c) SHA1(639baef8a9b347015d21817d69265700ff205774) ) /* Verified CG set for this version of PP0250 */
-	ROM_LOAD( "mgo-cg1019.u73",   0x08000, 0x8000, CRC(fb538a19) SHA1(1ed480ebdf3ad210511e7e0a0dd4e28466219ae9) ) /* Superseded by CG2015 which also works */
+	ROM_LOAD( "mro-cg1019.u72",   0x00000, 0x8000, CRC(9086dc3c) SHA1(639baef8a9b347015d21817d69265700ff205774) ) /* CG1019 or CG2015 works for this version of PP0250 */
+	ROM_LOAD( "mgo-cg1019.u73",   0x08000, 0x8000, CRC(fb538a19) SHA1(1ed480ebdf3ad210511e7e0a0dd4e28466219ae9) )
 	ROM_LOAD( "mbo-cg1019.u74",   0x10000, 0x8000, CRC(493bf604) SHA1(9cbce26ed328e6878ec5f6531ea140e1c17e6753) )
 	ROM_LOAD( "mxo-cg1019.u75",   0x18000, 0x8000, CRC(064a5c80) SHA1(4d21a7a424258f74d4a1e78c123288799e316228) )
 
@@ -5100,7 +5090,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
      Programs Available: PP0265, X000265P, PP0403 & PP0410 - Non Double-up Only
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0265_a46-a75.u68",   0x00000, 0x10000, CRC(dccb5e2f) SHA1(4c1ff0f79d9441d0b7e8b31f95def1056945eb96) ) /* Game Version: A46, Library Version: A75, Video Lib ver A0Y */
+	ROM_LOAD( "pp0265_a46-a75.u68",   0x00000, 0x10000, CRC(dccb5e2f) SHA1(4c1ff0f79d9441d0b7e8b31f95def1056945eb96) ) /* Game Version: A46, Library Version: A75, Video Lib ver A0Y - 10/32/95   @ IGT  L95-2447 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2003.u72",  0x00000, 0x8000, CRC(0d425f48) SHA1(b60aaf3f4bd76f75f72f6e8dda724bdf795cb521) ) /*  08/30/94   @ IGT  L95-0145  */
@@ -5178,7 +5168,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
 	ROM_LOAD( "cap740.u50", 0x0000, 0x0100, CRC(6fe619c4) SHA1(49e43dafd010ce0fe9b2a63b96a4ddedcb933c6d) )
 ROM_END
 
-ROM_START( pepp0274 ) /* Normal board : Standard Draw Poker (PP0274) - Normal Poker & Tournament Mode capable */
+ROM_START( pepp0274 ) /* Normal board : Standard Draw Poker (PP0274) - Tournament Mode capable */
 /*
 PayTable   Js+  2PR  3K  STR  FL  FH  4K  SF  RF  (Bonus)
 ---------------------------------------------------------
@@ -5233,7 +5223,7 @@ PayTable   3K   STR  FL  FH  4K  SF  5K  RF  4D  RF  (Bonus)
      Programs Available: PP0290, X000224P & PP0224 - Non Double-up Only
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0290_a47-a76.u68",   0x00000, 0x10000, CRC(907f9e80) SHA1(295953427c621c961e2f7241b074ecf87669351e) ) /* Game Version: A47, Library Version: A76 - 11/14/95  IGT  L96-0108 */
+	ROM_LOAD( "pp0290_a47-a76.u68",   0x00000, 0x10000, CRC(907f9e80) SHA1(295953427c621c961e2f7241b074ecf87669351e) ) /* Game Version: A47, Library Version: A76 - 11/14/95  @ IGT  L96-0108 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2133.u72",   0x00000, 0x8000, CRC(b21a789f) SHA1(c49f9b5f51c29bbc0e1392e86d6602bd44e46380) ) /*  02/02/95   @ IGT  L95-0276  */
@@ -5267,7 +5257,7 @@ PayTable   3K   STR  FL  FH  4K  SF  5K  RF  4D  RF  (Bonus)
 	ROM_LOAD( "cap773.u50", 0x0000, 0x0100, CRC(294b7b10) SHA1(a405a4b8547b713c5c02dacb19e7354095a7b584) )
 ROM_END
 
-ROM_START( pepp0291 ) /* Normal board : Deuces Wild Poker (No Double-up) (PP0291) - PSR Verified */
+ROM_START( pepp0291 ) /* Normal board : Deuces Wild Poker (PP0291) - PSR Verified */
 /*
                                         w/D     w/oD
 PayTable   3K   STR  FL  FH  4K  SF  5K  RF  4D  RF  (Bonus)
@@ -5289,7 +5279,7 @@ PayTable   3K   STR  FL  FH  4K  SF  5K  RF  4D  RF  (Bonus)
 	ROM_LOAD( "cap773.u50", 0x0000, 0x0100, CRC(294b7b10) SHA1(a405a4b8547b713c5c02dacb19e7354095a7b584) )
 ROM_END
 
-ROM_START( pepp0291a ) /* Normal board : Deuces Wild Poker (No Double-up) (PP0291) - PSR Verified */
+ROM_START( pepp0291a ) /* Normal board : Deuces Wild Poker (PP0291) - PSR Verified */
 /*
                                         w/D     w/oD
 PayTable   3K   STR  FL  FH  4K  SF  5K  RF  4D  RF  (Bonus)
@@ -5314,7 +5304,7 @@ ROM_END
 ROM_START( pepp0294 ) /* Normal board : Aces & Faces Bonus Joker Poker (PP0294) */
 /*
                                       2-10 J-K        w/J     w/oJ
-PayTable   Js+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  5K  RF  (Bonus)
+PayTable   Ks+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  5K  RF  (Bonus)
 --------------------------------------------------------------------------
   ????      1    1    2    3    5   7  14  20  25  50 100 200 400    800
   % Range: ???-???%  Optimum: ???%  Hit Frequency: ???%
@@ -5356,10 +5346,10 @@ PayTable   3K   STR  FL  FH  4K  SF  5K  RF  4D  4D  SD*  RF  (Bonus)
 	ROM_LOAD( "mxo-cg773.u75",   0x18000, 0x8000, CRC(75da0cd8) SHA1(4fb4eda9ae8e59884201368c7d8e4ff8b9967a4f) )
 
 	ROM_REGION( 0x100, "proms", 0 )
-	ROM_LOAD( "cap740.u50", 0x0000, 0x0100, CRC(6fe619c4) SHA1(49e43dafd010ce0fe9b2a63b96a4ddedcb933c6d) )
+	ROM_LOAD( "cap773.u50", 0x0000, 0x0100, CRC(294b7b10) SHA1(a405a4b8547b713c5c02dacb19e7354095a7b584) )
 ROM_END
 
-ROM_START( pepp0401 ) /* Normal board : 4 of a Kind Bonus Poker (No Double-up) (PP0401) - PSR Verified */
+ROM_START( pepp0401 ) /* Normal board : 4 of a Kind Bonus Poker (PP0401) - PSR Verified */
 /*
                                        5-K 2-4
 PayTable   Js+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
@@ -5381,7 +5371,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
 	ROM_LOAD( "cap740.u50", 0x0000, 0x0100, CRC(6fe619c4) SHA1(49e43dafd010ce0fe9b2a63b96a4ddedcb933c6d) )
 ROM_END
 
-ROM_START( pepp0409 ) /* Normal board : 4 of a Kind Bonus Poker (No Double-up) (PP0409) */
+ROM_START( pepp0409 ) /* Normal board : 4 of a Kind Bonus Poker (PP0409) - PSR Verified */
 /*
                                        5-K 2-4
 PayTable   Js+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
@@ -5391,7 +5381,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
      Programs Available: PP0203, X000203P, PP0590 & PP0409 - Non Double-up Only
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0409_a45-a75.u68",   0x00000, 0x10000, CRC(a71fdad9) SHA1(a719787895ad035b2b930d2692930466a9bfb19d) ) /* Game Version: A46, Library Version: A75, Game Lib ver: A0Y 02/11/96   IGT CO */
+	ROM_LOAD( "pp0409_a46-a75.u68",   0x00000, 0x10000, CRC(a71fdad9) SHA1(a719787895ad035b2b930d2692930466a9bfb19d) ) /* Game Version: A46, Library Version: A75, Game Lib ver: A0Y - 02/11/96   @ IGT CO */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2003.u72",  0x00000, 0x8000, CRC(0d425f48) SHA1(b60aaf3f4bd76f75f72f6e8dda724bdf795cb521) ) /*  08/30/94   @ IGT  L95-0145  */
@@ -5403,7 +5393,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
 	ROM_LOAD( "cap904.u50", 0x0000, 0x0100, CRC(0eec8336) SHA1(a6585c978dbc2f4f3818e3a5b92f8c28be23c4c0) )
 ROM_END
 
-ROM_START( pepp0410 ) /* Normal board : 4 of a Kind Bonus Poker (No Double-up) (PP0410) - PSR Verified */
+ROM_START( pepp0410 ) /* Normal board : 4 of a Kind Bonus Poker (PP0410) - PSR Verified */
 /*
                                        5-K 2-4
 PayTable   Js+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
@@ -5413,7 +5403,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
      Programs Available: PP0265, X000265P, PP0403 & PP0410 - Non Double-up Only
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0410_a46-a75.u68",   0x00000, 0x10000, CRC(41e904ae) SHA1(b63a47c91b9f76f11bd14ccb16dbb4ac86fe7926) ) /* Game Version: A46, Library Version: A75, Game Lib ver: A0Y */
+	ROM_LOAD( "pp0410_a46-a75.u68",   0x00000, 0x10000, CRC(41e904ae) SHA1(b63a47c91b9f76f11bd14ccb16dbb4ac86fe7926) ) /* Game Version: A46, Library Version: A75, Game Lib ver: A0Y - 02/11/96   @ IGT WII S */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2003.u72",  0x00000, 0x8000, CRC(0d425f48) SHA1(b60aaf3f4bd76f75f72f6e8dda724bdf795cb521) ) /*  08/30/94   @ IGT  L95-0145  */
@@ -5425,7 +5415,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
 	ROM_LOAD( "cap904.u50", 0x0000, 0x0100, CRC(0eec8336) SHA1(a6585c978dbc2f4f3818e3a5b92f8c28be23c4c0) )
 ROM_END
 
-ROM_START( pepp0410a ) /* Normal board : 4 of a Kind Bonus Poker (No Double-up) (PP0410) - PSR Verified */
+ROM_START( pepp0410a ) /* Normal board : 4 of a Kind Bonus Poker (PP0410) - PSR Verified */
 /*
                                        5-K 2-4
 PayTable   Js+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
@@ -5447,7 +5437,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
 	ROM_LOAD( "cap904.u50", 0x0000, 0x0100, CRC(0eec8336) SHA1(a6585c978dbc2f4f3818e3a5b92f8c28be23c4c0) )
 ROM_END
 
-ROM_START( pepp0417 ) /* Normal board : Deuces Wild Poker (No Double-up) (PP0417) - PSR Verified */
+ROM_START( pepp0417 ) /* Normal board : Deuces Wild Poker (PP0417) - PSR Verified */
 /*
                                         w/D     w/oD
 PayTable   3K   STR  FL  FH  4K  SF  5K  RF  4D  RF  (Bonus)
@@ -5469,7 +5459,7 @@ PayTable   3K   STR  FL  FH  4K  SF  5K  RF  4D  RF  (Bonus)
 	ROM_LOAD( "cap773.u50", 0x0000, 0x0100, CRC(294b7b10) SHA1(a405a4b8547b713c5c02dacb19e7354095a7b584) )
 ROM_END
 
-ROM_START( pepp0417a ) /* Normal board : Deuces Wild Poker (No Double-up) (PP0417) - PSR Verified */
+ROM_START( pepp0417a ) /* Normal board : Deuces Wild Poker (PP0417) - PSR Verified */
 /*
                                         w/D     w/oD
 PayTable   3K   STR  FL  FH  4K  SF  5K  RF  4D  RF  (Bonus)
@@ -5491,7 +5481,7 @@ PayTable   3K   STR  FL  FH  4K  SF  5K  RF  4D  RF  (Bonus)
 	ROM_LOAD( "cap773.u50", 0x0000, 0x0100, CRC(294b7b10) SHA1(a405a4b8547b713c5c02dacb19e7354095a7b584) )
 ROM_END
 
-ROM_START( pepp0418 ) /* Normal board : Deuces Wild Poker (No Double-up) (PP0418) - PSR Verified */
+ROM_START( pepp0418 ) /* Normal board : Deuces Wild Poker (PP0418) - PSR Verified */
 /*
                                         w/D     w/oD
 PayTable   3K   STR  FL  FH  4K  SF  5K  RF  4D  RF  (Bonus)
@@ -5501,7 +5491,7 @@ PayTable   3K   STR  FL  FH  4K  SF  5K  RF  4D  RF  (Bonus)
      Programs Available: PP0125, PP0418, X000291P & PP0291 - Non Double-up Only
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0418_a47-a76.u68",   0x00000, 0x10000, CRC(a0725de3) SHA1(fb2e7570862b48608041c833fc5c7c7198cbb041) ) /* Game Version: A47, Library Version: A76 - 11/13/95   IGT LA */
+	ROM_LOAD( "pp0418_a47-a76.u68",   0x00000, 0x10000, CRC(a0725de3) SHA1(fb2e7570862b48608041c833fc5c7c7198cbb041) ) /* Game Version: A47, Library Version: A76 - 11/13/95   @ IGT LA */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2133.u72",   0x00000, 0x8000, CRC(b21a789f) SHA1(c49f9b5f51c29bbc0e1392e86d6602bd44e46380) ) /*  02/02/95   @ IGT  L95-0276  */
@@ -5513,7 +5503,7 @@ PayTable   3K   STR  FL  FH  4K  SF  5K  RF  4D  RF  (Bonus)
 	ROM_LOAD( "cap773.u50", 0x0000, 0x0100, CRC(294b7b10) SHA1(a405a4b8547b713c5c02dacb19e7354095a7b584) )
 ROM_END
 
-ROM_START( pepp0419 ) /* Normal board : Standard Draw Poker (Auto Hold in options) (No Double-up) (PP0419) */
+ROM_START( pepp0419 ) /* Normal board : Standard Draw Poker (PP0419) */
 /*
 PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 ----------------------------------------------------------
@@ -5534,7 +5524,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 	ROM_LOAD( "cap740.u50", 0x0000, 0x0100, CRC(6fe619c4) SHA1(49e43dafd010ce0fe9b2a63b96a4ddedcb933c6d) )
 ROM_END
 
-ROM_START( pepp0420 ) /* Normal board : Standard Draw Poker (No Double-up) (PP0420) - requires SET chip to set denomination - PSR Verified */
+ROM_START( pepp0420 ) /* Normal board : Standard Draw Poker (PP0420) - requires SET chip to set denomination - PSR Verified */
 /*
 PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 ----------------------------------------------------------
@@ -5555,7 +5545,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 	ROM_LOAD( "cap740.u50", 0x0000, 0x0100, CRC(6fe619c4) SHA1(49e43dafd010ce0fe9b2a63b96a4ddedcb933c6d) )
 ROM_END
 
-ROM_START( pepp0423 ) /* Normal board : Standard Draw Poker (No Double-up) (PP0423) - PSR Verified */
+ROM_START( pepp0423 ) /* Normal board : Standard Draw Poker (PP0423) - PSR Verified */
 /*
 PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 ----------------------------------------------------------
@@ -5564,7 +5554,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
      Programs Available: PP0423
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0423_a45-a74.u68",   0x00000, 0x10000, CRC(b717bb0f) SHA1(89243bec0dc5b2c3907ef6579dfc3fdd28977971) ) /* Game Version: A45, Library Version: A74 */
+	ROM_LOAD( "pp0423_a45-a74.u68",   0x00000, 0x10000, CRC(b717bb0f) SHA1(89243bec0dc5b2c3907ef6579dfc3fdd28977971) ) /* Game Version: A45, Library Version: A74 - 02/08/96   @ IGT CO */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2004.u72",  0x00000, 0x8000, CRC(e5e40ea5) SHA1(e0d9e50b30cc0c25c932b2bf444990df1fb2c38c) ) /*  08/31/94   @ IGT  L95-0146  */
@@ -5576,7 +5566,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 	ROM_LOAD( "cap740.u50", 0x0000, 0x0100, CRC(6fe619c4) SHA1(49e43dafd010ce0fe9b2a63b96a4ddedcb933c6d) )
 ROM_END
 
-ROM_START( pepp0423a ) /* Normal board : Standard Draw Poker (No Double-up) (PP0423) - requires SET chip to set denomination - PSR Verified */
+ROM_START( pepp0423a ) /* Normal board : Standard Draw Poker (PP0423) - requires SET chip to set denomination - PSR Verified */
 /*
 PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 ----------------------------------------------------------
@@ -5585,7 +5575,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
      Programs Available: PP0423
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0423_896-914.u68",   0x00000, 0x10000, CRC(c996c539) SHA1(3874c294f4d223596ab537634aaf52bc0494ff85) ) /* Game Version: 896, Library Version: 914 */
+	ROM_LOAD( "pp0423_896-914.u68",   0x00000, 0x10000, CRC(c996c539) SHA1(3874c294f4d223596ab537634aaf52bc0494ff85) ) /* Game Version: 896, Library Version: 914 - 05/24/93   @ IGT MS */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2002.u72",  0x00000, 0x8000, CRC(d9d03979) SHA1(9729cbb2e5472eb652f8f549dd85047abe11cae0) ) /* 08/30/94   @IGT  */
@@ -5597,7 +5587,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 	ROM_LOAD( "cap740.u50", 0x0000, 0x0100, CRC(6fe619c4) SHA1(49e43dafd010ce0fe9b2a63b96a4ddedcb933c6d) )
 ROM_END
 
-ROM_START( pepp0423b ) /* Normal board : Standard Draw Poker (No Double-up) (PP0423) */
+ROM_START( pepp0423b ) /* Normal board : Standard Draw Poker (PP0423) */
 /*
 PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 ----------------------------------------------------------
@@ -5618,7 +5608,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 	ROM_LOAD( "cap740.u50", 0x0000, 0x0100, CRC(6fe619c4) SHA1(49e43dafd010ce0fe9b2a63b96a4ddedcb933c6d) )
 ROM_END
 
-ROM_START( pepp0423c ) /* Normal board : Standard Draw Poker (Auto Hold in options) (No Double-up) (PP0423) */
+ROM_START( pepp0423c ) /* Normal board : Standard Draw Poker (PP0423) */
 /*
 PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 ----------------------------------------------------------
@@ -5639,7 +5629,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 	ROM_LOAD( "cap740.u50", 0x0000, 0x0100, CRC(6fe619c4) SHA1(49e43dafd010ce0fe9b2a63b96a4ddedcb933c6d) )
 ROM_END
 
-ROM_START( pepp0426 ) /* Normal board : Joker Poker (No Double-up) (PP0426) - PSR Verified */
+ROM_START( pepp0426 ) /* Normal board : Joker Poker (PP0426) - PSR Verified */
 /*
                                             w/J     w/oJ
 PayTable   Ks+  2P  3K  STR  FL  FH  4K  SF  RF  5K  RF  (Bonus)
@@ -5661,7 +5651,7 @@ PayTable   Ks+  2P  3K  STR  FL  FH  4K  SF  RF  5K  RF  (Bonus)
 	ROM_LOAD( "cap740.u50", 0x0000, 0x0100, CRC(6fe619c4) SHA1(49e43dafd010ce0fe9b2a63b96a4ddedcb933c6d) )
 ROM_END
 
-ROM_START( pepp0428 ) /* Normal board : Joker Poker (No Double-up) (PP0428) - PSR Verified */
+ROM_START( pepp0428 ) /* Normal board : Joker Poker (PP0428) - PSR Verified */
 /*
                                             w/J     w/oJ
 PayTable   Ks+  2P  3K  STR  FL  FH  4K  SF  RF  5K  RF  (Bonus)
@@ -5683,7 +5673,7 @@ PayTable   Ks+  2P  3K  STR  FL  FH  4K  SF  RF  5K  RF  (Bonus)
 	ROM_LOAD( "cap740.u50", 0x0000, 0x0100, CRC(6fe619c4) SHA1(49e43dafd010ce0fe9b2a63b96a4ddedcb933c6d) )
 ROM_END
 
-ROM_START( pepp0429 ) /* Normal board : Joker Poker (Aces or Better) (No Double-up) (PP0429) - PSR Verified */
+ROM_START( pepp0429 ) /* Normal board : Joker Poker (Aces or Better) (PP0429) - PSR Verified */
 /*
                                             w/J     w/oJ
 PayTable   As   2P  3K  STR  FL  FH  4K  SF  RF  5K  RF  (Bonus)
@@ -5705,7 +5695,7 @@ PayTable   As   2P  3K  STR  FL  FH  4K  SF  RF  5K  RF  (Bonus)
 	ROM_LOAD( "cap740.u50", 0x0000, 0x0100, CRC(6fe619c4) SHA1(49e43dafd010ce0fe9b2a63b96a4ddedcb933c6d) )
 ROM_END
 
-ROM_START( pepp0429a ) /* Normal board : Joker Poker (Aces or Better) (No Double-up) (PP0429) - Must use a SET chip to set denomination - PSR Verified */
+ROM_START( pepp0429a ) /* Normal board : Joker Poker (Aces or Better) (PP0429) - Must use a SET chip to set denomination - PSR Verified */
 /*
                                             w/J     w/oJ
 PayTable   As   2P  3K  STR  FL  FH  4K  SF  RF  5K  RF  (Bonus)
@@ -5782,7 +5772,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
      Programs Available: PP0434, X000434P & PP0713 - Non Double-up Only
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0434_a45-a75.u68",   0x00000, 0x10000, CRC(e5c9ba19) SHA1(9a01457a54a0445a0f32affe2038366e681cada1) ) /* Game Version: A45, Library Version: A74 */
+	ROM_LOAD( "pp0434_a45-a75.u68",   0x00000, 0x10000, CRC(e5c9ba19) SHA1(9a01457a54a0445a0f32affe2038366e681cada1) ) /* Game Version: A45, Library Version: A74 - 12/12/95   @ IGT  L96-0263 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2004.u72",  0x00000, 0x8000, CRC(e5e40ea5) SHA1(e0d9e50b30cc0c25c932b2bf444990df1fb2c38c) ) /*  08/31/94   @ IGT  L95-0146  */
@@ -5818,7 +5808,7 @@ ROM_END
 ROM_START( pepp0445 ) /* Normal board : Aces & Faces Bonus Joker Poker (PP0445) */
 /*
                                       2-10 J-K        w/J     w/oJ
-PayTable   Js+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  5K  RF  (Bonus)
+PayTable   Ks+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  5K  RF  (Bonus)
 --------------------------------------------------------------------------
   ????      1    1    2    3    5   7  15  20  25  50 100 200 400    800
   % Range: ???-???%  Optimum: ???%  Hit Frequency: ???%
@@ -5846,7 +5836,7 @@ PayTable   Js+  2PR  3K  STR  FL  FH  4K  SF  RF  (Bonus)
      Programs Available: PP0132, PP0447, X000447P
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0447_a45-a74.u68",   0x00000, 0x10000, CRC(0ef0bb6c) SHA1(d0ef7a83417054f05d32d0a93ed0d5d618f4dfb9) ) /* Game Version: A45, Library Version: A74 */
+	ROM_LOAD( "pp0447_a45-a74.u68",   0x00000, 0x10000, CRC(0ef0bb6c) SHA1(d0ef7a83417054f05d32d0a93ed0d5d618f4dfb9) ) /* Game Version: A45, Library Version: A74 - 10/23/95   @ IGT  L95-2451 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2004.u72",  0x00000, 0x8000, CRC(e5e40ea5) SHA1(e0d9e50b30cc0c25c932b2bf444990df1fb2c38c) ) /*  08/31/94   @ IGT  L95-0146  */
@@ -6039,7 +6029,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
      Programs Available: PP0454, X000454P
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0454_a45-a75.u68",   0x00000, 0x10000, CRC(f15f751d) SHA1(6e73625bf3fe0461a171f72ab5478439207516b3) ) /* Game Version: A45, Library Version: A74 */
+	ROM_LOAD( "pp0454_a45-a75.u68",   0x00000, 0x10000, CRC(f15f751d) SHA1(6e73625bf3fe0461a171f72ab5478439207516b3) ) /* Game Version: A45, Library Version: A74 - 11/03/95   @ IGT  L96-0104 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2003.u72",  0x00000, 0x8000, CRC(0d425f48) SHA1(b60aaf3f4bd76f75f72f6e8dda724bdf795cb521) ) /*  08/30/94   @ IGT  L95-0145  */
@@ -6143,14 +6133,14 @@ ROM_START( pepp0467 ) /* Normal board : Unknown Bonus Poker (PP0467) */
                                          Four
 PayTable   Js+  2P  3K  STR  FL  FH  4K   7s* SF  RF  (Bonus)
 -------------------------------------------------------------
-  ????      1    2   3   4    5   8  25   25 50 250    800
+  ????      1    2   3   4    5   8  25   25  50 250    800
+  % Range: ???-???%  Optimum: ???%  Hit Frequency: ???%
      Programs Available: PP0467
 
-* Bonus for 4 Sevens
-
+* Extra bonus for 4 Sevens
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0467_823-854.u68",   0x00000, 0x10000, CRC(b19d48ae) SHA1(8a27a791e6f132d70d1ea02860e11fedb8515989) ) /* Game Version: 823, Library Version: 854 */
+	ROM_LOAD( "pp0467_823-854.u68",   0x00000, 0x10000, CRC(b19d48ae) SHA1(8a27a791e6f132d70d1ea02860e11fedb8515989) ) /* Game Version: 823, Library Version: 854 - 09/28/92   @ IGT  L92-1418 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2004.u72",  0x00000, 0x8000, CRC(e5e40ea5) SHA1(e0d9e50b30cc0c25c932b2bf444990df1fb2c38c) ) /*  08/31/94   @ IGT  L95-0146  */
@@ -6162,7 +6152,7 @@ PayTable   Js+  2P  3K  STR  FL  FH  4K   7s* SF  RF  (Bonus)
 	ROM_LOAD( "cap740.u50", 0x0000, 0x0100, CRC(6fe619c4) SHA1(49e43dafd010ce0fe9b2a63b96a4ddedcb933c6d) )
 ROM_END
 
-ROM_START( pepp0488 ) /* Normal board : Standard Draw Poker (PP0488) - 01/12/95   @ IGT  L95-0175 */
+ROM_START( pepp0488 ) /* Normal board : Standard Draw Poker (PP0488) - PSR Verified */
 /*
 PayTable   Js+  TP  3K  STR  FL  FH  4K  4A  SF  RF  (Bonus)
 ------------------------------------------------------------
@@ -6170,15 +6160,14 @@ PayTable   Js+  TP  3K  STR  FL  FH  4K  4A  SF  RF  (Bonus)
   % Range: 98.4-100.4%  Optimum: 102.4%  Hit Frequency: ???
 
 NOTE: This build / version is exclusive to Arizona Charlies
-      Use CG2004 + CAP740 graphics for a non-localized game
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0488_a30-a4v.u68",   0x00000, 0x10000, CRC(99849f5d) SHA1(643a303beda1c4a4619803071df5e612ab922eb9) ) /* Game Version: A30, Library Version: A4V */
+	ROM_LOAD( "pp0488_a30-a4v.u68",   0x00000, 0x10000, CRC(99849f5d) SHA1(643a303beda1c4a4619803071df5e612ab922eb9) ) /* Game Version: A30, Library Version: A4V - 01/12/95   @ IGT  L95-0175  */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
-	ROM_LOAD( "mro-cg2153.u72",   0x00000, 0x8000, CRC(004c9c8e) SHA1(ec3fa9d2c658de59e722d9979513d6b0c71d5742) ) /*  05/01/95   @ IGT  L95-1123  */
+	ROM_LOAD( "mro-cg2153.u72",   0x00000, 0x8000, CRC(004c9c8e) SHA1(ec3fa9d2c658de59e722d9979513d6b0c71d5742) ) /* Custom Arizona Charlie's Casino card backs - 05/01/95   @ IGT  L95-1123  */
 	ROM_LOAD( "mgo-cg2153.u73",   0x08000, 0x8000, CRC(e6843b35) SHA1(2d5219a3cb054ce8b470797c0496c7e24e94ed81) )
-	ROM_LOAD( "mbo-cg2153.u74",   0x10000, 0x8000, CRC(e3e28611) SHA1(d040f1df6203dc0bd6a79a391fb90fb930f8dd1a) ) /* Custom Arizona Charlie's Casino card backs */
+	ROM_LOAD( "mbo-cg2153.u74",   0x10000, 0x8000, CRC(e3e28611) SHA1(d040f1df6203dc0bd6a79a391fb90fb930f8dd1a) )
 	ROM_LOAD( "mxo-cg2153.u75",   0x18000, 0x8000, CRC(3ae44f7e) SHA1(00d625b60bffef6ce622cb50a3aa93b92131f578) )
 
 	ROM_REGION( 0x100, "proms", 0 )
@@ -6207,7 +6196,7 @@ PayTable   3K  STR  FL  FH  4K  SF  5K  RF  4D  RF  (Bonus)
 	ROM_LOAD( "cap773.u50", 0x0000, 0x0100, CRC(294b7b10) SHA1(a405a4b8547b713c5c02dacb19e7354095a7b584) )
 ROM_END
 
-ROM_START( pepp0509 ) /* Normal board : Standard Draw Poker (No Double-up) (PP0509) */
+ROM_START( pepp0509 ) /* Normal board : Standard Draw Poker (PP0509) */
 /*
 PayTable   Js+  TP  3K  STR  FL  FH  4K  SF  RF  (Bonus)
 --------------------------------------------------------
@@ -6216,7 +6205,7 @@ PayTable   Js+  TP  3K  STR  FL  FH  4K  SF  RF  (Bonus)
      Programs Available: PP0509
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0509_783-779.u68",   0x00000, 0x10000, CRC(a7c9b166) SHA1(3565070b9beba9aa50662253cafafa00f4f5abfa) ) /* Game Version: 782, Library Version: 779 */
+	ROM_LOAD( "pp0509_782-779.u68",   0x00000, 0x10000, CRC(a7c9b166) SHA1(3565070b9beba9aa50662253cafafa00f4f5abfa) ) /* Game Version: 782, Library Version: 779 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2004.u72",  0x00000, 0x8000, CRC(e5e40ea5) SHA1(e0d9e50b30cc0c25c932b2bf444990df1fb2c38c) ) /*  08/31/94   @ IGT  L95-0146  */
@@ -6228,7 +6217,7 @@ PayTable   Js+  TP  3K  STR  FL  FH  4K  SF  RF  (Bonus)
 	ROM_LOAD( "cap904.u50", 0x0000, 0x0100, CRC(0eec8336) SHA1(a6585c978dbc2f4f3818e3a5b92f8c28be23c4c0) )
 ROM_END
 
-ROM_START( pepp0510 ) /* Normal board : Standard Draw Poker (PP0510) - 11-24-92   @ IGT  L92-1614 */
+ROM_START( pepp0510 ) /* Normal board : Standard Draw Poker (PP0510) */
 /*
 PayTable   Js+  TP  3K  STR  FL  FH  4K  SF  RF  (Bonus)
 --------------------------------------------------------
@@ -6237,7 +6226,7 @@ PayTable   Js+  TP  3K  STR  FL  FH  4K  SF  RF  (Bonus)
      Programs Available: PP0510
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0510_782-779.u68",   0x00000, 0x10000, CRC(40ce3464) SHA1(230725ac3dd6eb6f891d4abfbcb4c41592531d4e) ) /* Game Version: 782, Library Version: 779 - 11-24-92   IGT  L92-1614 */
+	ROM_LOAD( "pp0510_782-779.u68",   0x00000, 0x10000, CRC(40ce3464) SHA1(230725ac3dd6eb6f891d4abfbcb4c41592531d4e) ) /* Game Version: 782, Library Version: 779 - 11-24-92   @ IGT  L92-1614 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2004.u72",  0x00000, 0x8000, CRC(e5e40ea5) SHA1(e0d9e50b30cc0c25c932b2bf444990df1fb2c38c) ) /*  08/31/94   @ IGT  L95-0146  */
@@ -6259,7 +6248,7 @@ PayTable   Js+  2PR  3K  STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
      Programs Available: PP0514, X000514P & PP0538 - Non Double-up Only
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0514_a46-a75.u68",   0x00000, 0x10000, CRC(53ca68c7) SHA1(2c46c89c6347bb8cf80b0ff85daabd0e925c87ec) ) /* Game Version: A46, Library Version: A75, Video Lib ver: A0Y - 11/15/95   IGT  L95-2471 */
+	ROM_LOAD( "pp0514_a46-a75.u68",   0x00000, 0x10000, CRC(53ca68c7) SHA1(2c46c89c6347bb8cf80b0ff85daabd0e925c87ec) ) /* Game Version: A46, Library Version: A75, Video Lib ver: A0Y - 11/15/95   @ IGT  L95-2471 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2003.u72",  0x00000, 0x8000, CRC(0d425f48) SHA1(b60aaf3f4bd76f75f72f6e8dda724bdf795cb521) ) /*  08/30/94   @ IGT  L95-0145  */
@@ -6325,7 +6314,7 @@ PayTable   Js+  2PR  3K  STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
      Programs Available: PP0515, X000515P & PP0539 - Non Double-up Only
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0515_a46-a75.u68",   0x00000, 0x10000, CRC(ad76895d) SHA1(cb82ad7b05e8962076ceed9e3aa6ead867e95539) ) /* Game Version: A46, Library Version: A75, Video Lib ver: A0Y - 11/13/95   IGT  L95-2474 */
+	ROM_LOAD( "pp0515_a46-a75.u68",   0x00000, 0x10000, CRC(ad76895d) SHA1(cb82ad7b05e8962076ceed9e3aa6ead867e95539) ) /* Game Version: A46, Library Version: A75, Video Lib ver: A0Y - 11/13/95   @ IGT  L95-2474 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2003.u72",  0x00000, 0x8000, CRC(0d425f48) SHA1(b60aaf3f4bd76f75f72f6e8dda724bdf795cb521) ) /*  08/30/94   @ IGT  L95-0145  */
@@ -6347,7 +6336,7 @@ PayTable   Js+  2PR  3K  STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
      Programs Available: PP0515, X000515P & PP0539 - Non Double-up Only
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0515_a0n-a23.u68",   0x00000, 0x10000, CRC(76389889) SHA1(992fb7d3f296d1cecab75ab4cf13fff1b7a5cc11) ) /* Game Version: A0N, Library Version: A23, Video Lib ver: A0Y - 04/19/94   IGT  L94-0949 */
+	ROM_LOAD( "pp0515_a0n-a23.u68",   0x00000, 0x10000, CRC(76389889) SHA1(992fb7d3f296d1cecab75ab4cf13fff1b7a5cc11) ) /* Game Version: A0N, Library Version: A23, Video Lib ver: A0Y - 04/19/94   @ IGT  L94-0949 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2003.u72",  0x00000, 0x8000, CRC(0d425f48) SHA1(b60aaf3f4bd76f75f72f6e8dda724bdf795cb521) ) /*  08/30/94   @ IGT  L95-0145  */
@@ -6413,7 +6402,7 @@ PayTable   Js+  2PR  3K  STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
      Programs Available: PP0516, X000516P & PP0540 - Non Double-up Only
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0516_a46-a75.u68",   0x00000, 0x10000, CRC(6e226711) SHA1(71930ec43c4b75ca50971242be79459976882546) ) /* Game Version: A46, Library Version: A75, Video Lib ver: A0Y - 11/13/95   IGT  L95-2475 */
+	ROM_LOAD( "pp0516_a46-a75.u68",   0x00000, 0x10000, CRC(6e226711) SHA1(71930ec43c4b75ca50971242be79459976882546) ) /* Game Version: A46, Library Version: A75, Video Lib ver: A0Y - 11/13/95   @ IGT  L95-2475 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2003.u72",  0x00000, 0x8000, CRC(0d425f48) SHA1(b60aaf3f4bd76f75f72f6e8dda724bdf795cb521) ) /*  08/30/94   @ IGT  L95-0145  */
@@ -6435,7 +6424,7 @@ PayTable   Js+  2PR  3K  STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
      Programs Available: PP0516, X000516P & PP0540 - Non Double-up Only
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0516_989-974.u68",   0x00000, 0x10000, CRC(d9da6e13) SHA1(421678d9cb42daaf5b21074cc3900db914dd26cf) ) /* Game Version: 989, Library Version: 974 , Video Lib ver: A0Y */
+	ROM_LOAD( "pp0516_989-974.u68",   0x00000, 0x10000, CRC(d9da6e13) SHA1(421678d9cb42daaf5b21074cc3900db914dd26cf) ) /* Game Version: 989, Library Version: 974 , Video Lib ver: A0Y - 12/20/93   @ IGT  L94-0041 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2003.u72",  0x00000, 0x8000, CRC(0d425f48) SHA1(b60aaf3f4bd76f75f72f6e8dda724bdf795cb521) ) /*  08/30/94   @ IGT  L95-0145  */
@@ -6469,7 +6458,7 @@ PayTable   Js+  2PR  3K  STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
 	ROM_LOAD( "cap740.u50", 0x0000, 0x0100, CRC(6fe619c4) SHA1(49e43dafd010ce0fe9b2a63b96a4ddedcb933c6d) )
 ROM_END
 
-ROM_START( pepp0526 ) /* Normal board :  Deuces Wild Poker (Auto Hold in options) (PP0526) */
+ROM_START( pepp0526 ) /* Normal board :  Deuces Wild Poker (PP0526) */
 /*
                                         w/D     w/oD
 PayTable   3K   STR  FL  FH  4K  SF  5K  RF  4D  RF  (Bonus)
@@ -6535,7 +6524,7 @@ PayTable   Ks+  2P  3K  STR  FL  FH  4K  SF  RF  5K  RF  (Bonus)
 	ROM_LOAD( "cap740.u50", 0x0000, 0x0100, CRC(6fe619c4) SHA1(49e43dafd010ce0fe9b2a63b96a4ddedcb933c6d) )
 ROM_END
 
-ROM_START( pepp0538 ) /* Normal board : Double Bonus Poker (No Double-up) (PP0538) - PSR Verified */
+ROM_START( pepp0538 ) /* Normal board : Double Bonus Poker (PP0538) - PSR Verified */
 /*
                                       5-K 2-4
 PayTable   Js+  2PR  3K  STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
@@ -6545,7 +6534,7 @@ PayTable   Js+  2PR  3K  STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
      Programs Available: PP0514, X000514P & PP0538 - Non Double-up Only
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0538_a46-a75.u68",   0x00000, 0x10000, CRC(f9e8dbe7) SHA1(dd745a48764f7da7314236016bf9c7fa67a78fad) ) /* Game Version: A46, Library Version: A75, Video Lib ver: A0Y - 02/13/96   IGT CO */
+	ROM_LOAD( "pp0538_a46-a75.u68",   0x00000, 0x10000, CRC(f9e8dbe7) SHA1(dd745a48764f7da7314236016bf9c7fa67a78fad) ) /* Game Version: A46, Library Version: A75, Video Lib ver: A0Y - 02/13/96   @ IGT CO */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2003.u72",  0x00000, 0x8000, CRC(0d425f48) SHA1(b60aaf3f4bd76f75f72f6e8dda724bdf795cb521) ) /*  08/30/94   @ IGT  L95-0145  */
@@ -6557,7 +6546,7 @@ PayTable   Js+  2PR  3K  STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
 	ROM_LOAD( "cap904.u50", 0x0000, 0x0100, CRC(0eec8336) SHA1(a6585c978dbc2f4f3818e3a5b92f8c28be23c4c0) )
 ROM_END
 
-ROM_START( pepp0540 ) /* Normal board : Double Bonus Poker (No Double-up) (PP0540) */
+ROM_START( pepp0540 ) /* Normal board : Double Bonus Poker (PP0540) */
 /*
                                       5-K 2-4
 PayTable   Js+  2PR  3K  STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
@@ -6567,7 +6556,7 @@ PayTable   Js+  2PR  3K  STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
      Programs Available: PP0516, X000516P & PP0540 - Non Double-up Only
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0540_974-a0y.u68",   0x00000, 0x10000, CRC(b39e0c13) SHA1(a0dd05eb2927792efb1f432dbbd4a9a4fd6ad4c9) ) /* Game Version: 974, Library Version: A0Y */
+	ROM_LOAD( "pp0540_974-a0y.u68",   0x00000, 0x10000, CRC(b39e0c13) SHA1(a0dd05eb2927792efb1f432dbbd4a9a4fd6ad4c9) ) /* Game Version: 974, Library Version: A0Y - 02/13/96   @ IGT CO */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2003.u72",  0x00000, 0x8000, CRC(0d425f48) SHA1(b60aaf3f4bd76f75f72f6e8dda724bdf795cb521) ) /*  08/30/94   @ IGT  L95-0145  */
@@ -6655,7 +6644,7 @@ PayTable   2P  3K  STR  FL  FH  4K  SF  RF  5K  RF  (Bonus)
      Programs Available: PP0550, X000550P
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0550_a6k-a9g.u68",   0x00000, 0x10000, CRC(1de4ee32) SHA1(0e06a43e7e3988cc2fddd1a57af724f5421d2ca4) ) /* Game Version: A6K, Library Version: A9G - 05/21/98   IGT NJ */
+	ROM_LOAD( "pp0550_a6k-a9g.u68",   0x00000, 0x10000, CRC(1de4ee32) SHA1(0e06a43e7e3988cc2fddd1a57af724f5421d2ca4) ) /* Game Version: A6K, Library Version: A9G - 05/21/98   @ IGT NJ */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2004.u72",  0x00000, 0x8000, CRC(e5e40ea5) SHA1(e0d9e50b30cc0c25c932b2bf444990df1fb2c38c) ) /*  08/31/94   @ IGT  L95-0146  */
@@ -6713,7 +6702,7 @@ Internally the program reports a 99.40% return.
 	ROM_LOAD( "cap904.u50", 0x0000, 0x0100, CRC(0eec8336) SHA1(a6585c978dbc2f4f3818e3a5b92f8c28be23c4c0) )
 ROM_END
 
-ROM_START( pepp0559 ) /* Normal board : Joker Poker (Aces or Better) (Auto Hold in options) (PP0559) */
+ROM_START( pepp0559 ) /* Normal board : Joker Poker (Aces or Better) (PP0559) */
 /*
                                             w/J     w/oJ
 PayTable   As   2P  3K  STR  FL  FH  4K  SF  RF  5K  RF  (Bonus)
@@ -6735,7 +6724,7 @@ PayTable   As   2P  3K  STR  FL  FH  4K  SF  RF  5K  RF  (Bonus)
 	ROM_LOAD( "cap904.u50", 0x0000, 0x0100, CRC(0eec8336) SHA1(a6585c978dbc2f4f3818e3a5b92f8c28be23c4c0) )
 ROM_END
 
-ROM_START( pepp0562 ) /* Normal board : 10's or Better (Auto Hold in options) (PP0562) */
+ROM_START( pepp0562 ) /* Normal board : 10's or Better (PP0562) */
 /*
 PayTable  10s+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 ----------------------------------------------------------
@@ -6778,7 +6767,7 @@ PayTable   Ks+  2P  3K  STR  FL  FH  4K  SF  RF  5K  RF  (Bonus)
 	ROM_LOAD( "cap740.u50", 0x0000, 0x0100, CRC(6fe619c4) SHA1(49e43dafd010ce0fe9b2a63b96a4ddedcb933c6d) )
 ROM_END
 
-ROM_START( pepp0585 ) /* Normal board : Standard Draw Poker (No Double-up) (PP0585) */
+ROM_START( pepp0585 ) /* Normal board : Standard Draw Poker (PP0585) */
 /*
 
 PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
@@ -6807,10 +6796,9 @@ PayTable   Js+  2PR  3K  STR  FL  FH  4K  SF  RF  (Bonus)
   CA        1    2    3   4    6   9  25  50 250    800
   % Range: 95.5-97.5%  Optimum: 99.5%  Hit Frequency: 45.5%
      Programs Available: PP0587
-
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0587_a45-a74.u68",   0x00000, 0x10000, CRC(b45f0725) SHA1(1bedfa12211de1cef0b25214c38a10094b248d63) ) /* Game Version: A45, Library Version: A74 - 02/12/96   IGT CO */
+	ROM_LOAD( "pp0587_a45-a74.u68",   0x00000, 0x10000, CRC(b45f0725) SHA1(1bedfa12211de1cef0b25214c38a10094b248d63) ) /* Game Version: A45, Library Version: A74 - 02/12/96   @ IGT CO */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2004.u72",  0x00000, 0x8000, CRC(e5e40ea5) SHA1(e0d9e50b30cc0c25c932b2bf444990df1fb2c38c) ) /*  08/31/94   @ IGT  L95-0146  */
@@ -6836,7 +6824,7 @@ PayTable   Js+  2PR  3K  STR  FL  FH  4K  4K  4A  SF  RF     (Bonus)
 Currently errors out with CCOM LINK DOWN as CCOM linking is not supported
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0596_a41-a5y.u68",   0x00000, 0x10000, CRC(18475dfe) SHA1(98b8dfd98ce163e78e5c6e80b31dcc58d3ee74e6) ) /* Game Version: A45, Library Version: A5Y, Video Lib Ver: A4N - 09/05/95   IGT NJ */
+	ROM_LOAD( "pp0596_a41-a5y.u68",   0x00000, 0x10000, CRC(18475dfe) SHA1(98b8dfd98ce163e78e5c6e80b31dcc58d3ee74e6) ) /* Game Version: A45, Library Version: A5Y, Video Lib Ver: A4N - 09/05/95   @ IGT NJ */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2093.u72",   0x00000, 0x8000, BAD_DUMP CRC(1380bfa6) SHA1(4c3512770afee29d1d9b384a2ea2ad59018f1d4e) ) /* corruption in some graphics */
@@ -6862,7 +6850,7 @@ PayTable   Js+  2PR  3K  STR  FL  FH  4K  4K  4A  SF  RF     (Bonus)
 Currently errors out with CCOM LINK DOWN as CCOM linking is not supported
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0598_a41-a96.u68",   0x00000, 0x10000, CRC(075295db) SHA1(7cb238d4df7be7e393dcfe7102aeffa13b1454d9) ) /* Game Version: A45, Library Version: A96, Video Lib Ver: A4N - 12/21/95   IGT MS */
+	ROM_LOAD( "pp0598_a41-a96.u68",   0x00000, 0x10000, CRC(075295db) SHA1(7cb238d4df7be7e393dcfe7102aeffa13b1454d9) ) /* Game Version: A45, Library Version: A96, Video Lib Ver: A4N - 12/21/95   @ IGT MS */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2093.u72",   0x00000, 0x8000, BAD_DUMP CRC(1380bfa6) SHA1(4c3512770afee29d1d9b384a2ea2ad59018f1d4e) ) /* corruption in some graphics */
@@ -6874,7 +6862,7 @@ Currently errors out with CCOM LINK DOWN as CCOM linking is not supported
 	ROM_LOAD( "cap779.u50", 0x0000, 0x0100, CRC(b04a98fd) SHA1(4788c7cb88aa692a55855ca65e092df43506e55a) )
 ROM_END
 
-ROM_START( pepp0711 ) /* Normal board : Bonus Poker Deluxe (No Double-up) (PP0711) - PSR Verified */
+ROM_START( pepp0711 ) /* Normal board : Bonus Poker Deluxe (PP0711) - PSR Verified */
 /*
 PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 ----------------------------------------------------------
@@ -6895,7 +6883,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 	ROM_LOAD( "cap740.u50", 0x0000, 0x0100, CRC(6fe619c4) SHA1(49e43dafd010ce0fe9b2a63b96a4ddedcb933c6d) )
 ROM_END
 
-ROM_START( pepp0713 ) /* Normal board : Bonus Poker Deluxe (No Double-up) (PP0713) - PSR Verified */
+ROM_START( pepp0713 ) /* Normal board : Bonus Poker Deluxe (PP0713) - PSR Verified */
 /*
 PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 ----------------------------------------------------------
@@ -6982,7 +6970,7 @@ PayTable   Js+  2PR  3K  STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
 	ROM_LOAD( "cap904.u50", 0x0000, 0x0100, CRC(0eec8336) SHA1(a6585c978dbc2f4f3818e3a5b92f8c28be23c4c0) )
 ROM_END
 
-ROM_START( pepp0728 ) /* Normal board : Double Bonus Poker (PP0728) - 11/30/95   @ IGT  L96-0247 - PSR Verified */
+ROM_START( pepp0728 ) /* Normal board : Double Bonus Poker (PP0728) - PSR Verified */
 /*
                                       5-K 2-4
 PayTable   Js+  2PR  3K  STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
@@ -6992,7 +6980,7 @@ P437A/4K/5  1    1    3   4    5   6  50  80 160  50 250    800
      Programs Available: PP0728
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0728_a46-a75.u68",   0x00000, 0x10000, CRC(ecfbdb77) SHA1(072dc5d59b6a705591045162612b5101e85e1b10) )/* Game Version: A46, Library Version: A75, Video Lib ver: A0Y - 11/30/95   IGT  L96-0247 */
+	ROM_LOAD( "pp0728_a46-a75.u68",   0x00000, 0x10000, CRC(ecfbdb77) SHA1(072dc5d59b6a705591045162612b5101e85e1b10) )/* Game Version: A46, Library Version: A75, Video Lib ver: A0Y - 11/30/95   @ IGT  L96-0247 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2003.u72",  0x00000, 0x8000, CRC(0d425f48) SHA1(b60aaf3f4bd76f75f72f6e8dda724bdf795cb521) ) /*  08/30/94   @ IGT  L95-0145  */
@@ -7015,7 +7003,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
      Programs Available: PP0733
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0733_a4y-a6g.u68",   0x00000, 0x10000, CRC(027e8e0c) SHA1(8735a6d9cc59ac5ecb615a4e437fb5beaac0dc9f) ) /* Game Version: A4Y, Library Version: A6G, Video Lib Ver: A0Y - 05/09/96   IGT MS */
+	ROM_LOAD( "pp0733_a4y-a6g.u68",   0x00000, 0x10000, CRC(027e8e0c) SHA1(8735a6d9cc59ac5ecb615a4e437fb5beaac0dc9f) ) /* Game Version: A4Y, Library Version: A6G, Video Lib Ver: A0Y - 05/09/96   @ IGT MS */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2135.u72",  0x00000, 0x8000, CRC(ecb5c319) SHA1(8c6dce009017c919b4ebfeb0292cfb8819b652a0) ) /*  02/08/95   @ IGT  MS  */
@@ -7037,7 +7025,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
      Programs Available: PP0750
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0750_979-a0c.u68",   0x00000, 0x10000, CRC(2224c865) SHA1(6080c29d69c847603b79b7b15f65b32e36d305d8) ) /* Game Version: 979, Library Version: A0C - 01/23/95   IGT MS */
+	ROM_LOAD( "pp0750_979-a0c.u68",   0x00000, 0x10000, CRC(2224c865) SHA1(6080c29d69c847603b79b7b15f65b32e36d305d8) ) /* Game Version: 979, Library Version: A0C - 01/23/95   @ IGT MS */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2004.u72",  0x00000, 0x8000, CRC(e5e40ea5) SHA1(e0d9e50b30cc0c25c932b2bf444990df1fb2c38c) ) /*  08/31/94   @ IGT  L95-0146  */
@@ -7059,7 +7047,7 @@ PayTable   8s+  2P  3K  STR  FL  FH  4K  SF  RF  5K   RF  (Bonus)
      Programs Available: PP0757
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0757_a5v-a6d.u68",   0x00000, 0x10000, CRC(dcf3004f) SHA1(c095a874a8813f7100ec430e034530eeb93c4117) ) /* Game Version: A5V, Library Version: A6D - 11/08/96   IGT  L97-0062 */
+	ROM_LOAD( "pp0757_a5v-a6d.u68",   0x00000, 0x10000, CRC(dcf3004f) SHA1(c095a874a8813f7100ec430e034530eeb93c4117) ) /* Game Version: A5V, Library Version: A6D - 11/08/96   @ IGT  L97-0062 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2015.u72",   0x00000, 0x8000, CRC(7f73ee5c) SHA1(b6c5d423c8176555c1f32605c328ffbfcf94b656) ) /* Verified CG set for PP0760 set */
@@ -7124,7 +7112,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
      Programs Available: PP0764, X000764P
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0764_a46-a75.u68",   0x00000, 0x10000, CRC(9176732a) SHA1(4a9898334aa76c483757addb3a28ace71b008c7e) ) /* Game Version: A46, Library Version: A75, Game Lib ver: A0Y - 11/03/96   IGT  L96-0250 */
+	ROM_LOAD( "pp0764_a46-a75.u68",   0x00000, 0x10000, CRC(9176732a) SHA1(4a9898334aa76c483757addb3a28ace71b008c7e) ) /* Game Version: A46, Library Version: A75, Game Lib ver: A0Y - 11/03/96   @ IGT  L96-0250 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2003.u72",  0x00000, 0x8000, CRC(0d425f48) SHA1(b60aaf3f4bd76f75f72f6e8dda724bdf795cb521) ) /*  08/30/94   @ IGT  L95-0145  */
@@ -7198,7 +7186,7 @@ PayTable   3K   STR  FL  FH  4K  SF  5K   RF    4D   RF   4D  (Bonus)
      Programs Available: PP0812
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "pp0812_a47-a76.u68",   0x00000, 0x10000, CRC(0de2a7ec) SHA1(fedb8da0608328a9d33e46af18de25004b1d03de) ) /* Game Version: A47, Library Version: A76 - 06/18/96   IGT  L96-1818 */
+	ROM_LOAD( "pp0812_a47-a76.u68",   0x00000, 0x10000, CRC(0de2a7ec) SHA1(fedb8da0608328a9d33e46af18de25004b1d03de) ) /* Game Version: A47, Library Version: A76 - 06/18/96   @ IGT  L96-1818 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2133.u72",   0x00000, 0x8000, CRC(b21a789f) SHA1(c49f9b5f51c29bbc0e1392e86d6602bd44e46380) ) /*  02/02/95   @ IGT  L95-0276  */
@@ -7997,11 +7985,11 @@ ROM_END
 
 ROM_START( peke0017 ) /* Normal board : Keno 1-10 Spot (KE0017) */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "ke0017_560-a07.u68",  0x00000, 0x08000, CRC(a0f70116) SHA1(15808cd3245e2e5934f3365f95590da0be552e8b) ) /* Game Version: 560, Library Version: A07 - 02/11/94   IGT  L94-0689 */
+	ROM_LOAD( "ke0017_560-a07.u68",  0x00000, 0x08000, CRC(a0f70116) SHA1(15808cd3245e2e5934f3365f95590da0be552e8b) ) /* Game Version: 560, Library Version: A07 - 02/11/94   @ IGT  L94-0689 */
 	ROM_RELOAD(                      0x08000, 0x8000) /* 32K version built using earlier gaming libraries */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
-	ROM_LOAD( "mro-cg1016.u72",  0x00000, 0x8000, CRC(92072064) SHA1(ccd12303afb559a57f135f5feff1eada4394c45b) ) /* 03/04/91   IGT  L91-0306 */
+	ROM_LOAD( "mro-cg1016.u72",  0x00000, 0x8000, CRC(92072064) SHA1(ccd12303afb559a57f135f5feff1eada4394c45b) ) /* 03/04/91   IGT  @ L91-0306 */
 	ROM_LOAD( "mgo-cg1016.u73",  0x08000, 0x8000, CRC(fd54f031) SHA1(0990338d00574d798bed2c13ed2cf65118698a65) )
 	ROM_LOAD( "mbo-cg1016.u74",  0x10000, 0x8000, CRC(6325ff0b) SHA1(cca693b42d458024d11badf02923f0aedc5252ba) )
 	ROM_LOAD( "mxo-cg1016.u75",  0x18000, 0x8000, CRC(54345a8c) SHA1(928f1633343a1d81ef193ebd09de0d36c52057ca) )
@@ -8012,10 +8000,10 @@ ROM_END
 
 ROM_START( peke1001 ) /* Normal board : Keno 2-10 Spot (KE1001) - Payout 85.02%, Paytable 85-H - PSR Verified */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "ke1001_590-a77.u68",   0x00000, 0x10000, CRC(a3dfee24) SHA1(f6c4822dbaab67319fc05ac0a0b2cd03313eb1e6) ) /* Game Version: 590, Library Version: A77 - 09/08/99   IGT  L99-1902 */
+	ROM_LOAD( "ke1001_590-a77.u68",   0x00000, 0x10000, CRC(a3dfee24) SHA1(f6c4822dbaab67319fc05ac0a0b2cd03313eb1e6) ) /* Game Version: 590, Library Version: A77 - 09/08/99   @ IGT  L99-1902 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
-	ROM_LOAD( "mro-cg1267.u72",  0x00000, 0x8000, CRC(16498b57) SHA1(9c22726299af7204c4be1c6d8afc4c1b512ad918) ) /* 03/24/94   IGT  L94-0873 */
+	ROM_LOAD( "mro-cg1267.u72",  0x00000, 0x8000, CRC(16498b57) SHA1(9c22726299af7204c4be1c6d8afc4c1b512ad918) ) /* 03/24/94   @ IGT  L94-0873 */
 	ROM_LOAD( "mgo-cg1267.u73",  0x08000, 0x8000, CRC(80847c5a) SHA1(8422cd13a91c3c462af5efcfca8615e7eeaa2e52) )
 	ROM_LOAD( "mbo-cg1267.u74",  0x10000, 0x8000, CRC(ce7af8a7) SHA1(38675122c764b8fa9260246ea99ac0f0750da277) )
 	ROM_LOAD( "mxo-cg1267.u75",  0x18000, 0x8000, CRC(a4394303) SHA1(30a07028de35f74cc4fb776b0505ca743c8d7b5b) )
@@ -8029,7 +8017,7 @@ ROM_START( peke1006 ) /* Normal board : Keno 2-10 Spot (KE1006) - Payout 87.61%,
 	ROM_LOAD( "ke1006_590-a77.u68",   0x00000, 0x10000, CRC(5f2a9aac) SHA1(67d24e376d0dcea30d68c3019919e02261c38d7d) ) /* Game Version: 590, Library Version: A77 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
-	ROM_LOAD( "mro-cg1267.u72",  0x00000, 0x8000, CRC(16498b57) SHA1(9c22726299af7204c4be1c6d8afc4c1b512ad918) ) /* 03/24/94   IGT  L94-0873 */
+	ROM_LOAD( "mro-cg1267.u72",  0x00000, 0x8000, CRC(16498b57) SHA1(9c22726299af7204c4be1c6d8afc4c1b512ad918) ) /* 03/24/94   @ IGT  L94-0873 */
 	ROM_LOAD( "mgo-cg1267.u73",  0x08000, 0x8000, CRC(80847c5a) SHA1(8422cd13a91c3c462af5efcfca8615e7eeaa2e52) )
 	ROM_LOAD( "mbo-cg1267.u74",  0x10000, 0x8000, CRC(ce7af8a7) SHA1(38675122c764b8fa9260246ea99ac0f0750da277) )
 	ROM_LOAD( "mxo-cg1267.u75",  0x18000, 0x8000, CRC(a4394303) SHA1(30a07028de35f74cc4fb776b0505ca743c8d7b5b) )
@@ -8040,10 +8028,10 @@ ROM_END
 
 ROM_START( peke1012 ) /* Normal board : Keno 1-10 Spot (KE1012) - Payout 90.27%, Paytable 90-P - PSR Verified */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "ke1012_590-a77.u68",   0x00000, 0x10000, CRC(18ec2146) SHA1(6a5bae2accd15f8e5efa18d26dcadb2bec7b6163) ) /* Game Version: 582, Library Version: A77 - 09/09/99   IGT MNI S */
+	ROM_LOAD( "ke1012_590-a77.u68",   0x00000, 0x10000, CRC(18ec2146) SHA1(6a5bae2accd15f8e5efa18d26dcadb2bec7b6163) ) /* Game Version: 582, Library Version: A77 - 09/09/99   @ IGT MNI S */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
-	ROM_LOAD( "mro-cg1267.u72",  0x00000, 0x8000, CRC(16498b57) SHA1(9c22726299af7204c4be1c6d8afc4c1b512ad918) ) /* 03/24/94   IGT  L94-0873 */
+	ROM_LOAD( "mro-cg1267.u72",  0x00000, 0x8000, CRC(16498b57) SHA1(9c22726299af7204c4be1c6d8afc4c1b512ad918) ) /* 03/24/94   @ IGT  L94-0873 */
 	ROM_LOAD( "mgo-cg1267.u73",  0x08000, 0x8000, CRC(80847c5a) SHA1(8422cd13a91c3c462af5efcfca8615e7eeaa2e52) )
 	ROM_LOAD( "mbo-cg1267.u74",  0x10000, 0x8000, CRC(ce7af8a7) SHA1(38675122c764b8fa9260246ea99ac0f0750da277) )
 	ROM_LOAD( "mxo-cg1267.u75",  0x18000, 0x8000, CRC(a4394303) SHA1(30a07028de35f74cc4fb776b0505ca743c8d7b5b) )
@@ -8054,10 +8042,10 @@ ROM_END
 
 ROM_START( peke1012a ) /* Normal board : Keno 1-10 Spot (KE1012) - Payout 90.27%, Paytable 90-P - PSR Verified */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "ke1012_582-a77.u68",   0x00000, 0x10000, CRC(87f696ba) SHA1(de6cc7ff799218ae6fb75521243534484ef4b9a8) ) /* Game Version: 582, Library Version: A77 - 10/23/95   IGT  L95-2454 */
+	ROM_LOAD( "ke1012_582-a77.u68",   0x00000, 0x10000, CRC(87f696ba) SHA1(de6cc7ff799218ae6fb75521243534484ef4b9a8) ) /* Game Version: 582, Library Version: A77 - 10/23/95   @ IGT  L95-2454 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
-	ROM_LOAD( "mro-cg1267.u72",  0x00000, 0x8000, CRC(16498b57) SHA1(9c22726299af7204c4be1c6d8afc4c1b512ad918) ) /* 03/24/94   IGT  L94-0873 */
+	ROM_LOAD( "mro-cg1267.u72",  0x00000, 0x8000, CRC(16498b57) SHA1(9c22726299af7204c4be1c6d8afc4c1b512ad918) ) /* 03/24/94   @ IGT  L94-0873 */
 	ROM_LOAD( "mgo-cg1267.u73",  0x08000, 0x8000, CRC(80847c5a) SHA1(8422cd13a91c3c462af5efcfca8615e7eeaa2e52) )
 	ROM_LOAD( "mbo-cg1267.u74",  0x10000, 0x8000, CRC(ce7af8a7) SHA1(38675122c764b8fa9260246ea99ac0f0750da277) )
 	ROM_LOAD( "mxo-cg1267.u75",  0x18000, 0x8000, CRC(a4394303) SHA1(30a07028de35f74cc4fb776b0505ca743c8d7b5b) )
@@ -8068,10 +8056,10 @@ ROM_END
 
 ROM_START( peke1012b ) /* Normal board : Keno 1-10 Spot (KE1012) - Payout 90.27%, Paytable 90-P */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "ke1012_576-a3u.u68",   0x00000, 0x10000, CRC(470e8c10) SHA1(f8a65a3a73477e9e9d2f582eeefa93b470497dfa) ) /* Game Version: 576, Library Version: A3U - 08/03/94   IGT L94-1550 */
+	ROM_LOAD( "ke1012_576-a3u.u68",   0x00000, 0x10000, CRC(470e8c10) SHA1(f8a65a3a73477e9e9d2f582eeefa93b470497dfa) ) /* Game Version: 576, Library Version: A3U - 08/03/94   @ IGT L94-1550 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
-	ROM_LOAD( "mro-cg1267.u72",  0x00000, 0x8000, CRC(16498b57) SHA1(9c22726299af7204c4be1c6d8afc4c1b512ad918) ) /* 03/24/94   IGT  L94-0873 */
+	ROM_LOAD( "mro-cg1267.u72",  0x00000, 0x8000, CRC(16498b57) SHA1(9c22726299af7204c4be1c6d8afc4c1b512ad918) ) /* 03/24/94   @ IGT  L94-0873 */
 	ROM_LOAD( "mgo-cg1267.u73",  0x08000, 0x8000, CRC(80847c5a) SHA1(8422cd13a91c3c462af5efcfca8615e7eeaa2e52) )
 	ROM_LOAD( "mbo-cg1267.u74",  0x10000, 0x8000, CRC(ce7af8a7) SHA1(38675122c764b8fa9260246ea99ac0f0750da277) )
 	ROM_LOAD( "mxo-cg1267.u75",  0x18000, 0x8000, CRC(a4394303) SHA1(30a07028de35f74cc4fb776b0505ca743c8d7b5b) )
@@ -8085,7 +8073,7 @@ ROM_START( peke1013 ) /* Normal board : Keno 2-10 Spot (KE1013) - Payout 91.97%,
 	ROM_LOAD( "ke1013_686-a8r.u68",   0x00000, 0x10000, CRC(97ae2ee7) SHA1(df680ff46320e21a352406e2eaf92003f86434a4) ) /* Game Version: 686, Library Version: A8R */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
-	ROM_LOAD( "mro-cg1267.u72",  0x00000, 0x8000, CRC(16498b57) SHA1(9c22726299af7204c4be1c6d8afc4c1b512ad918) ) /* 03/24/94   IGT  L94-0873 */
+	ROM_LOAD( "mro-cg1267.u72",  0x00000, 0x8000, CRC(16498b57) SHA1(9c22726299af7204c4be1c6d8afc4c1b512ad918) ) /* 03/24/94   @ IGT  L94-0873 */
 	ROM_LOAD( "mgo-cg1267.u73",  0x08000, 0x8000, CRC(80847c5a) SHA1(8422cd13a91c3c462af5efcfca8615e7eeaa2e52) )
 	ROM_LOAD( "mbo-cg1267.u74",  0x10000, 0x8000, CRC(ce7af8a7) SHA1(38675122c764b8fa9260246ea99ac0f0750da277) )
 	ROM_LOAD( "mxo-cg1267.u75",  0x18000, 0x8000, CRC(a4394303) SHA1(30a07028de35f74cc4fb776b0505ca743c8d7b5b) )
@@ -8099,7 +8087,7 @@ ROM_START( peke1013a ) /* Normal board : Keno 2-10 Spot (KE1013) - Payout 91.97%
 	ROM_LOAD( "ke1013_590-a77.u68",   0x00000, 0x10000, CRC(3b178f94) SHA1(c601150a728d750b73f949ba6e2d2979c4c4be2e) ) /* Game Version: 590, Library Version: A77 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
-	ROM_LOAD( "mro-cg1267.u72",  0x00000, 0x8000, CRC(16498b57) SHA1(9c22726299af7204c4be1c6d8afc4c1b512ad918) ) /* 03/24/94   IGT  L94-0873 */
+	ROM_LOAD( "mro-cg1267.u72",  0x00000, 0x8000, CRC(16498b57) SHA1(9c22726299af7204c4be1c6d8afc4c1b512ad918) ) /* 03/24/94   @ IGT  L94-0873 */
 	ROM_LOAD( "mgo-cg1267.u73",  0x08000, 0x8000, CRC(80847c5a) SHA1(8422cd13a91c3c462af5efcfca8615e7eeaa2e52) )
 	ROM_LOAD( "mbo-cg1267.u74",  0x10000, 0x8000, CRC(ce7af8a7) SHA1(38675122c764b8fa9260246ea99ac0f0750da277) )
 	ROM_LOAD( "mxo-cg1267.u75",  0x18000, 0x8000, CRC(a4394303) SHA1(30a07028de35f74cc4fb776b0505ca743c8d7b5b) )
@@ -8894,7 +8882,7 @@ PayTable   3K   STR  FL  FH  4K  SF  5K  RF  4D  RF  (Bonus)
      Programs Available: PP0055, X000055P, PP0723
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "xp000040.u67",   0x00000, 0x10000, CRC(7b30b1d5) SHA1(394c964cf6269a4cd9b9debe8f4a5a0c96db06a7) ) /*  10/23/96   IGT  L96-2682 */
+	ROM_LOAD( "xp000040.u67",   0x00000, 0x10000, CRC(7b30b1d5) SHA1(394c964cf6269a4cd9b9debe8f4a5a0c96db06a7) ) /*  10/23/96   @ IGT  L96-2682 */
 
 	ROM_REGION( 0x10000, "user1", 0 )
 	ROM_LOAD( "x000055p.u66",   0x00000, 0x10000, CRC(e06819df) SHA1(36590c4588b8036908e63714fbb3e77d23e60eae) ) /* Deuces Wild Poker */
@@ -9069,7 +9057,7 @@ PayTable   3K   STR  FL  FH  4K  SF  5K  RF  4D  RF  (Bonus)
      Programs Available: PP0055, X000055P, PP0723
 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "xp000095.u67",   0x00000, 0x10000, CRC(6a1679ea) SHA1(421e8c9eacc8e397267a48cad7ae96f541b1c19a) ) /*  12/19/97   IGT  L98-0197 */
+	ROM_LOAD( "xp000095.u67",   0x00000, 0x10000, CRC(6a1679ea) SHA1(421e8c9eacc8e397267a48cad7ae96f541b1c19a) ) /*  12/19/97   @ IGT  L98-0197 */
 
 	ROM_REGION( 0x10000, "user1", 0 )
 	ROM_LOAD( "x000055p.u66",   0x00000, 0x10000, CRC(e06819df) SHA1(36590c4588b8036908e63714fbb3e77d23e60eae) ) /* Deuces Wild Poker */
@@ -9423,7 +9411,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  SF  RF  (Bonus)
 	ROM_LOAD( "xp000038.u67",   0x00000, 0x10000, CRC(8707ab9e) SHA1(3e00a2ad8017e1495c6d6fe900d0efa68a1772b8) ) /*  09/05/95   @ IGT  L95-2452 */
 
 	ROM_REGION( 0x10000, "user1", 0 )
-	ROM_LOAD( "x000060p.u66",   0x00000, 0x10000, CRC(1ec1ad4d) SHA1(19bc46fe86e0ff23c43ffc072b1c461b60481f0f) ) /* Standard Draw Poker */
+	ROM_LOAD( "x000060p.u66",   0x00000, 0x10000, CRC(1ec1ad4d) SHA1(19bc46fe86e0ff23c43ffc072b1c461b60481f0f) ) /* Standard Draw Poker - 02/28/95   @ IGT  AZI */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2242.u77",  0x00000, 0x8000, CRC(963a7e7d) SHA1(ebb159f6c731a3f912382745ef9a9c6d4fa2fc99) ) /*  03/19/96   @ IGT  L96-0703 */
@@ -9645,7 +9633,7 @@ PayTable   3K   STR  FL  FH  4K  SF  5K  RF  4D  RF  (Bonus)
 	ROM_LOAD( "xp000038.u67",   0x00000, 0x10000, CRC(8707ab9e) SHA1(3e00a2ad8017e1495c6d6fe900d0efa68a1772b8) ) /*  09/05/95   @ IGT  L95-2452 */
 
 	ROM_REGION( 0x10000, "user1", 0 )
-	ROM_LOAD( "x000224p.u66",   0x00000, 0x10000, CRC(69ca6ac7) SHA1(e6f119b69f769a1f484a4ced3eb4d9e5406f0b09) ) /* Deuces Wild Poker - 10/31/94   IGT  L94-2065 */
+	ROM_LOAD( "x000224p.u66",   0x00000, 0x10000, CRC(69ca6ac7) SHA1(e6f119b69f769a1f484a4ced3eb4d9e5406f0b09) ) /* Deuces Wild Poker - 10/31/94   @ IGT  L94-2065 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2242.u77",  0x00000, 0x8000, CRC(963a7e7d) SHA1(ebb159f6c731a3f912382745ef9a9c6d4fa2fc99) ) /*  03/19/96   @ IGT  L96-0703 */
@@ -10410,7 +10398,7 @@ PayTable   Ks+  2P  3K  STR  FL  FH  4K  SF  RF  5K  RF  (Bonus)
 	ROM_LOAD( "xp000038.u67",   0x00000, 0x10000, CRC(8707ab9e) SHA1(3e00a2ad8017e1495c6d6fe900d0efa68a1772b8) ) /*  09/05/95   @ IGT  L95-2452 */
 
 	ROM_REGION( 0x10000, "user1", 0 )
-	ROM_LOAD( "x000588p.u66",   0x00000, 0x10000, CRC(baa448cc) SHA1(0f1da407304f7dafbe06119d068f7caf99404cb4) ) /* Joker Poker - 10/31/94   IGT  L94-2068 */
+	ROM_LOAD( "x000588p.u66",   0x00000, 0x10000, CRC(baa448cc) SHA1(0f1da407304f7dafbe06119d068f7caf99404cb4) ) /* Joker Poker - 10/31/94   @ IGT  L94-2068 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2242.u77",  0x00000, 0x8000, CRC(963a7e7d) SHA1(ebb159f6c731a3f912382745ef9a9c6d4fa2fc99) ) /*  03/19/96   @ IGT  L96-0703 */
@@ -10435,7 +10423,7 @@ PayTable   Js+  2PR  3K  STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
 	ROM_LOAD( "xp000038.u67",   0x00000, 0x10000, CRC(8707ab9e) SHA1(3e00a2ad8017e1495c6d6fe900d0efa68a1772b8) ) /*  09/05/95   @ IGT  L95-2452 */
 
 	ROM_REGION( 0x10000, "user1", 0 )
-	ROM_LOAD( "x000725p.u66",   0x00000, 0x10000, CRC(a56f3910) SHA1(06d0d4a8722e033ff1fbe0947135952ce8274725) ) /* Double Bonus Poker - 03/13/95   IGT MSI S */
+	ROM_LOAD( "x000725p.u66",   0x00000, 0x10000, CRC(a56f3910) SHA1(06d0d4a8722e033ff1fbe0947135952ce8274725) ) /* Double Bonus Poker - 03/13/95   @ IGT MSI S */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2242.u77",  0x00000, 0x8000, CRC(963a7e7d) SHA1(ebb159f6c731a3f912382745ef9a9c6d4fa2fc99) ) /*  03/19/96   @ IGT  L96-0703 */
@@ -10510,7 +10498,7 @@ PayTable   Js+  2PR  3K   STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
 	ROM_LOAD( "xp000038.u67",   0x00000, 0x10000, CRC(8707ab9e) SHA1(3e00a2ad8017e1495c6d6fe900d0efa68a1772b8) ) /*  09/05/95   @ IGT  L95-2452 */
 
 	ROM_REGION( 0x10000, "user1", 0 )
-	ROM_LOAD( "x000763p.u66",   0x00000, 0x10000, CRC(bf7dda7d) SHA1(1a6089d1159c199199e608f3dd2ba7b45a29b31c) ) /* 4 of a Kind Bonus Poker */
+	ROM_LOAD( "x000763p.u66",   0x00000, 0x10000, CRC(bf7dda7d) SHA1(1a6089d1159c199199e608f3dd2ba7b45a29b31c) ) /* 4 of a Kind Bonus Poker - 05/30/95   @IGT  L95-1278  */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2242.u77",  0x00000, 0x8000, CRC(963a7e7d) SHA1(ebb159f6c731a3f912382745ef9a9c6d4fa2fc99) ) /*  03/19/96   @ IGT  L96-0703 */
@@ -10563,7 +10551,7 @@ NOTE: Same payout as X002068P but internally reports a return of 96.7% instead o
 	ROM_LOAD( "xp000038.u67",   0x00000, 0x10000, CRC(8707ab9e) SHA1(3e00a2ad8017e1495c6d6fe900d0efa68a1772b8) ) /*  09/05/95   @ IGT  L95-2452 */
 
 	ROM_REGION( 0x10000, "user1", 0 )
-	ROM_LOAD( "x002002p.u66",   0x00000, 0x10000, CRC(4af4b14a) SHA1(f6695dea3267c80ea5b2ccb06b98bb8ff7a81a98) ) /* Double Double Bonus Poker - 01/19/95   @IGT  L95-0364 */
+	ROM_LOAD( "x002002p.u66",   0x00000, 0x10000, CRC(4af4b14a) SHA1(f6695dea3267c80ea5b2ccb06b98bb8ff7a81a98) ) /* Double Double Bonus Poker - 01/19/95   @ IGT  L95-0364 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2242.u77",  0x00000, 0x8000, CRC(963a7e7d) SHA1(ebb159f6c731a3f912382745ef9a9c6d4fa2fc99) ) /*  03/19/96   @ IGT  L96-0703 */
@@ -10768,7 +10756,7 @@ PayTable   3K  STR  FL  FH  4K  SF  RF  5K  5K  5A  4D  4D  RF  (Bonus)
 	ROM_LOAD( "xp000019.u67",   0x00000, 0x10000, CRC(8ac876eb) SHA1(105b4aee2692ccb20795586ccbdf722c59db66cf) )
 
 	ROM_REGION( 0x10000, "user1", 0 )
-	ROM_LOAD( "x002026p.u66",   0x00000, 0x10000, CRC(7fcbc10a) SHA1(5d50b356ae1a3461a5916b469f85b690b086e675) ) /* Deuces Wild Bonus Poker - 04/06/95   IGT CO */
+	ROM_LOAD( "x002026p.u66",   0x00000, 0x10000, CRC(7fcbc10a) SHA1(5d50b356ae1a3461a5916b469f85b690b086e675) ) /* Deuces Wild Bonus Poker - 04/06/95   @ IGT CO */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2159.u77",  0x00000, 0x8000, CRC(7dce6da3) SHA1(4722f0b558b057e4cb934304d44509a2d651b128) ) /*  05/17/95   @ IGT  L95-1308  */
@@ -10843,7 +10831,7 @@ PayTable   3K  STR  FL  FH  4K  SF  RF  5K  5K  5A  4D  4D  RF  (Bonus)
 	ROM_LOAD( "xp000019.u67",   0x00000, 0x10000, CRC(8ac876eb) SHA1(105b4aee2692ccb20795586ccbdf722c59db66cf) )
 
 	ROM_REGION( 0x10000, "user1", 0 )
-	ROM_LOAD( "x002029p.u66",   0x00000, 0x10000, CRC(e2f6fb89) SHA1(4b60b580b00b4268d1cb9065ffe0d21f8fa6a931) ) /* Deuces Wild Bonus Poker - 04/06/95   IGT  L95-1001 */
+	ROM_LOAD( "x002029p.u66",   0x00000, 0x10000, CRC(e2f6fb89) SHA1(4b60b580b00b4268d1cb9065ffe0d21f8fa6a931) ) /* Deuces Wild Bonus Poker - 04/06/95   @ IGT  L95-1001 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2159.u77",  0x00000, 0x8000, CRC(7dce6da3) SHA1(4722f0b558b057e4cb934304d44509a2d651b128) ) /*  05/17/95   @ IGT  L95-1308  */
@@ -10946,7 +10934,7 @@ PayTable   Js+  2PR  3K  STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
 	ROM_LOAD( "xp000038.u67",   0x00000, 0x10000, CRC(8707ab9e) SHA1(3e00a2ad8017e1495c6d6fe900d0efa68a1772b8) ) /*  09/05/95   @ IGT  L95-2452 */
 
 	ROM_REGION( 0x10000, "user1", 0 )
-	ROM_LOAD( "x002035p.u66",   0x00000, 0x10000, CRC(dc3f0742) SHA1(d57cf3353b81f41895458019e47203f98645f17a) ) /* White Hot Aces Poker - 05/02/95   IGT CO */
+	ROM_LOAD( "x002035p.u66",   0x00000, 0x10000, CRC(dc3f0742) SHA1(d57cf3353b81f41895458019e47203f98645f17a) ) /* White Hot Aces Poker - 05/02/95   @ IGT CO */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2242.u77",  0x00000, 0x8000, CRC(963a7e7d) SHA1(ebb159f6c731a3f912382745ef9a9c6d4fa2fc99) ) /*  03/19/96   @ IGT  L96-0703 */
@@ -10971,7 +10959,7 @@ PayTable   Js+  2PR  3K  STR  FL  FH  4K  4K  4A  SF  RF  (Bonus)
 	ROM_LOAD( "xp000038.u67",   0x00000, 0x10000, CRC(8707ab9e) SHA1(3e00a2ad8017e1495c6d6fe900d0efa68a1772b8) ) /*  09/05/95   @ IGT  L95-2452 */
 
 	ROM_REGION( 0x10000, "user1", 0 )
-	ROM_LOAD( "x002036p.u66",   0x00000, 0x10000, CRC(69207baf) SHA1(fe038b969106ae5cdc8dde1c06497be9c7b5b8bf) ) /* White Hot Aces Poker - 05/02/95   IGT CO */
+	ROM_LOAD( "x002036p.u66",   0x00000, 0x10000, CRC(69207baf) SHA1(fe038b969106ae5cdc8dde1c06497be9c7b5b8bf) ) /* White Hot Aces Poker - 05/02/95   @ IGT CO */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2242.u77",  0x00000, 0x8000, CRC(963a7e7d) SHA1(ebb159f6c731a3f912382745ef9a9c6d4fa2fc99) ) /*  03/19/96   @ IGT  L96-0703 */
@@ -11021,7 +11009,7 @@ PayTable   Js+  2PR  3K  3A  STR  FL  FH  4K  4A  SF  RF  (Bonus)
 	ROM_LOAD( "xp000038.u67",   0x00000, 0x10000, CRC(8707ab9e) SHA1(3e00a2ad8017e1495c6d6fe900d0efa68a1772b8) ) /*  09/05/95   @ IGT  L95-2452 */
 
 	ROM_REGION( 0x10000, "user1", 0 )
-	ROM_LOAD( "x002038p.u66",   0x00000, 0x10000, CRC(58d01ba5) SHA1(6d4cde9c9e55967db2b661c7123cce9958a00639) ) /* Nevada Bonus Poker - 05/02/95   IGT LA */
+	ROM_LOAD( "x002038p.u66",   0x00000, 0x10000, CRC(58d01ba5) SHA1(6d4cde9c9e55967db2b661c7123cce9958a00639) ) /* Nevada Bonus Poker - 05/02/95   @ IGT LA */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 	ROM_LOAD( "mro-cg2242.u77",  0x00000, 0x8000, CRC(963a7e7d) SHA1(ebb159f6c731a3f912382745ef9a9c6d4fa2fc99) ) /*  03/19/96   @ IGT  L96-0703 */
@@ -12027,7 +12015,7 @@ Also compatible with:
 	ROM_LOAD( "x002270p.u66",   0x00000, 0x10000, CRC(d3cffd4d) SHA1(6fcba550ee62d66f947aa5ab45b1e7dd66854475) ) /* Jackpot Poker */
 
 	ROM_REGION( 0x040000, "gfx1", 0 )
-	ROM_LOAD( "mro-cg2292.u77",  0x00000, 0x10000, CRC(10da5df3) SHA1(0975acc2151957c0d9996d5cc77ded6deefbb41a) )
+	ROM_LOAD( "mro-cg2292.u77",  0x00000, 0x10000, CRC(10da5df3) SHA1(0975acc2151957c0d9996d5cc77ded6deefbb41a) ) /*  01/24/96   @ IGT AZI */
 	ROM_LOAD( "mgo-cg2292.u78",  0x10000, 0x10000, CRC(92fc6282) SHA1(8d765326dd604274dcf36e38440a1f9c404a020a) )
 	ROM_LOAD( "mbo-cg2292.u79",  0x20000, 0x10000, CRC(996ab79c) SHA1(54469ce8de6aa35d6be996fc87b677d75f7cfa68) )
 	ROM_LOAD( "mxo-cg2292.u80",  0x30000, 0x10000, CRC(d7efa5c9) SHA1(40aa7593b358c99f3f98c5d5ad11e186aff17b58) )
@@ -12291,7 +12279,7 @@ Also compatible with:
 	ROM_LOAD( "x002297p.u66",   0x00000, 0x10000, CRC(7ebe809e) SHA1(5aafdf499455b8c96f6d780894cc442ed21e0dc2) ) /* Jackpot Poker */
 
 	ROM_REGION( 0x040000, "gfx1", 0 )
-	ROM_LOAD( "mro-cg2292.u77",  0x00000, 0x10000, CRC(10da5df3) SHA1(0975acc2151957c0d9996d5cc77ded6deefbb41a) )
+	ROM_LOAD( "mro-cg2292.u77",  0x00000, 0x10000, CRC(10da5df3) SHA1(0975acc2151957c0d9996d5cc77ded6deefbb41a) ) /*  01/24/96   @ IGT AZI */
 	ROM_LOAD( "mgo-cg2292.u78",  0x10000, 0x10000, CRC(92fc6282) SHA1(8d765326dd604274dcf36e38440a1f9c404a020a) )
 	ROM_LOAD( "mbo-cg2292.u79",  0x20000, 0x10000, CRC(996ab79c) SHA1(54469ce8de6aa35d6be996fc87b677d75f7cfa68) )
 	ROM_LOAD( "mxo-cg2292.u80",  0x30000, 0x10000, CRC(d7efa5c9) SHA1(40aa7593b358c99f3f98c5d5ad11e186aff17b58) )
@@ -12323,7 +12311,7 @@ Also compatible with:
 	ROM_LOAD( "x002297p.u66",   0x00000, 0x10000, CRC(7ebe809e) SHA1(5aafdf499455b8c96f6d780894cc442ed21e0dc2) ) /* Jackpot Poker */
 
 	ROM_REGION( 0x040000, "gfx1", 0 )
-	ROM_LOAD( "mro-cg2292.u77",  0x00000, 0x10000, CRC(10da5df3) SHA1(0975acc2151957c0d9996d5cc77ded6deefbb41a) )
+	ROM_LOAD( "mro-cg2292.u77",  0x00000, 0x10000, CRC(10da5df3) SHA1(0975acc2151957c0d9996d5cc77ded6deefbb41a) ) /*  01/24/96   @ IGT AZI */
 	ROM_LOAD( "mgo-cg2292.u78",  0x10000, 0x10000, CRC(92fc6282) SHA1(8d765326dd604274dcf36e38440a1f9c404a020a) )
 	ROM_LOAD( "mbo-cg2292.u79",  0x20000, 0x10000, CRC(996ab79c) SHA1(54469ce8de6aa35d6be996fc87b677d75f7cfa68) )
 	ROM_LOAD( "mxo-cg2292.u80",  0x30000, 0x10000, CRC(d7efa5c9) SHA1(40aa7593b358c99f3f98c5d5ad11e186aff17b58) )
@@ -13278,7 +13266,7 @@ ROM_START( pex0006k ) /* Superboard : Keno (X000006K+XK000001) Paytable: 87-C, P
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
 
-	ROM_LOAD( "mro-cg2120.u77",  0x00000, 0x8000, CRC(bb607f11) SHA1(575b5a0bea07864c2f7a42f4e5ff5c8d586b652d) ) /* 04/25/95   IGT  L95-1503 */
+	ROM_LOAD( "mro-cg2120.u77",  0x00000, 0x8000, CRC(bb607f11) SHA1(575b5a0bea07864c2f7a42f4e5ff5c8d586b652d) ) /* 04/25/95   @ IGT  L95-1503 */
 	ROM_LOAD( "mgo-cg2120.u78",  0x08000, 0x8000, CRC(aa5fc2a4) SHA1(576b06e01751d78bd948c4b0eef9c519750028c8) )
 	ROM_LOAD( "mbo-cg2120.u79",  0x10000, 0x8000, CRC(1f2f7d66) SHA1(56e0b6d05c148aa9262350cfcd0ae3a2fa7974c3) )
 	ROM_LOAD( "mxo-cg2120.u80",  0x18000, 0x8000, CRC(c4696495) SHA1(45b5ecba73cf590ac5685d951664bc73fdb02940) )
@@ -13289,13 +13277,13 @@ ROM_END
 
 ROM_START( pex0013k ) /* Superboard : Keno (X000013K+XK000011) Paytable: 91-D, Payout Percentage: 91.97 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "xk000011.u67",   0x00000, 0x10000, CRC(bad69e8d) SHA1(b742ba30654636e8f339cabcd13793f5452caf5a) ) /* 09/09/99   IGT IN */
+	ROM_LOAD( "xk000011.u67",   0x00000, 0x10000, CRC(bad69e8d) SHA1(b742ba30654636e8f339cabcd13793f5452caf5a) ) /* 09/09/99   @ IGT IN */
 
 	ROM_REGION( 0x10000, "user1", 0 )
-	ROM_LOAD( "x000013k.u66",   0x00000, 0x10000, CRC(e8ed1053) SHA1(9f373ad28c341a0a586f4d077fbab4c93e4c0632) ) /* 01/22/95   L95-0617 */
+	ROM_LOAD( "x000013k.u66",   0x00000, 0x10000, CRC(e8ed1053) SHA1(9f373ad28c341a0a586f4d077fbab4c93e4c0632) ) /* 01/22/95   @ L95-0617 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
-	ROM_LOAD( "mro-cg2120.u77",  0x00000, 0x8000, CRC(bb607f11) SHA1(575b5a0bea07864c2f7a42f4e5ff5c8d586b652d) ) /* 04/25/95   IGT  L95-1503 */
+	ROM_LOAD( "mro-cg2120.u77",  0x00000, 0x8000, CRC(bb607f11) SHA1(575b5a0bea07864c2f7a42f4e5ff5c8d586b652d) ) /* 04/25/95   @ IGT  L95-1503 */
 	ROM_LOAD( "mgo-cg2120.u78",  0x08000, 0x8000, CRC(aa5fc2a4) SHA1(576b06e01751d78bd948c4b0eef9c519750028c8) )
 	ROM_LOAD( "mbo-cg2120.u79",  0x10000, 0x8000, CRC(1f2f7d66) SHA1(56e0b6d05c148aa9262350cfcd0ae3a2fa7974c3) )
 	ROM_LOAD( "mxo-cg2120.u80",  0x18000, 0x8000, CRC(c4696495) SHA1(45b5ecba73cf590ac5685d951664bc73fdb02940) )
@@ -13306,13 +13294,13 @@ ROM_END
 
 ROM_START( pex0013ka ) /* Superboard : Keno (X000013K+XK000012) Paytable: 91-D, Payout Percentage: 91.97 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
-	ROM_LOAD( "xk000012.u67",   0x00000, 0x10000, CRC(435a6393) SHA1(5b4684750228c4264aea896a91a52bc13bb28516) ) /* 09/09/99   IGT  L99-1811 */
+	ROM_LOAD( "xk000012.u67",   0x00000, 0x10000, CRC(435a6393) SHA1(5b4684750228c4264aea896a91a52bc13bb28516) ) /* 09/09/99   @ IGT  L99-1811 */
 
 	ROM_REGION( 0x10000, "user1", 0 )
-	ROM_LOAD( "x000013k.u66",   0x00000, 0x10000, CRC(e8ed1053) SHA1(9f373ad28c341a0a586f4d077fbab4c93e4c0632) ) /* 01/22/95   L95-0617 */
+	ROM_LOAD( "x000013k.u66",   0x00000, 0x10000, CRC(e8ed1053) SHA1(9f373ad28c341a0a586f4d077fbab4c93e4c0632) ) /* 01/22/95   @ L95-0617 */
 
 	ROM_REGION( 0x020000, "gfx1", 0 )
-	ROM_LOAD( "mro-cg2120.u77",  0x00000, 0x8000, CRC(bb607f11) SHA1(575b5a0bea07864c2f7a42f4e5ff5c8d586b652d) ) /* 04/25/95   IGT  L95-1503 */
+	ROM_LOAD( "mro-cg2120.u77",  0x00000, 0x8000, CRC(bb607f11) SHA1(575b5a0bea07864c2f7a42f4e5ff5c8d586b652d) ) /* 04/25/95   @ IGT  L95-1503 */
 	ROM_LOAD( "mgo-cg2120.u78",  0x08000, 0x8000, CRC(aa5fc2a4) SHA1(576b06e01751d78bd948c4b0eef9c519750028c8) )
 	ROM_LOAD( "mbo-cg2120.u79",  0x10000, 0x8000, CRC(1f2f7d66) SHA1(56e0b6d05c148aa9262350cfcd0ae3a2fa7974c3) )
 	ROM_LOAD( "mxo-cg2120.u80",  0x18000, 0x8000, CRC(c4696495) SHA1(45b5ecba73cf590ac5685d951664bc73fdb02940) )
@@ -13755,13 +13743,75 @@ Joker Poker          P17A      95.50%
 	ROM_LOAD( "capx2174.u43", 0x0000, 0x0200, CRC(50bdad55) SHA1(958d463c7effb3457c1f9c44c9b7822339c04e8b) )
 ROM_END
 
-ROM_START( pexmp013 ) /* Superboard : 5-in-1 Wingboard (XMP00013) Program in Spanish, Requires Spanish Wingboard CG rom set */
 /*
 
-The CG2346 set seems to support all games supported in CG2298 as well as graphics support for the following XnnnnnnP Data game types:
+Known Wingboard compatible program roms:
+
+   XMP00007 (CG2298+CAPX2298 - not dumped)
+   XMP00009 (CG2230+CAPX2230 - not dumped - MGM exclusive)
+   XMP00011
+   XMP00013 - Spanish
+   XMP00014 - International (CG2352+CAPX2352 - not dumped)
+   XMP00017
+   XMP00022 - Spanish
+   XMP00026 - Spanish
+   XMP00030
+
+Wingboard programs are not compatible with:
+ Lucky Deal Poker, Shockwave Poker, Ace$ Bonus Poker, Jackpot Poker, any mid-hand pay games like
+ Dealt Deuces Bonus, Barbaric Deuces, Pay the Ace (No Face) or any other specialty poker games.
+
+The CG2298 graphics can support the following XnnnnnnP Data game types (as displayed):
+
+  Bonus Poker, Bonus Poker Dlx, Crazy Eights, Deluxe Deuces, Deuces Joker, Deuces Bonus, Deuces Wild
+  Double Bonus, Double Deuces, Dbl Dbl Bonus, Double Joker, Jacks or Better, Joker Poker, Loose Deuces
+  Nevada Bonus, Nevada Draw, Odds & Ends, Full House Bonus, Royal Deuces, Sevens or Better, Tens or Better
+  Triple Bonus, Two Pair, White Hot Aces
+
+  Super Aces shows as just Bonus Poker, Triple Bonus Poker Plus shows as just Triple Bonus
+
+
+The CG2346 Spanish set supports all games supported in CG2298 as well as graphics support for the following XnnnnnnP Data game types:
   Triple Double Bonus, Black Jack Poker
 
+The CG2426 set supersedes CG2298 and adds graphics support for the following XnnnnnnP Data game types (as displayed):
+  BlackJack Bonus, Tpl Dbl Bonus, Super Dbl Bonus
+
+The CG2451 set supersedes CG2298 & CG2426 and adds graphics support for the following XnnnnnnP Data game types (as displayed):
+  Dbl Dbl Bonus Plus
+
 */
+
+ROM_START( pexmp011 ) /* Superboard : 5-in-1 Wingboard (XMP00011) - PSR Verified */
+	ROM_REGION( 0x10000, "maincpu", 0 )
+	ROM_LOAD( "xmp00011.u67",   0x00000, 0x10000, CRC(540c90a3) SHA1(9ba25e1669d07c4985fcde5043f555af6bb2fe40) ) /*  04/11/97   @ IGT  MO  */
+
+	ROM_REGION( 0x10000, "user1", 0 )
+	ROM_LOAD( "x000006p.u66",   0x00000, 0x10000, CRC(0ee609a1) SHA1(57043ac2c6ff4377479dd7b66d7e379053f3f602) ) /* Standard Draw Poker - 03/23/95   @ IGT  L95-0826 */
+
+	ROM_REGION( 0x10000, "user2", 0 )
+	ROM_LOAD( "x000057p.u66",   0x00000, 0x10000, CRC(2046710a) SHA1(3fcc7c3069ea54d0e4982814aca1d7b327bb2074) ) /* Deuces Wild Poker - 05/04/95   @ IGT  L95-1143 */
+
+	ROM_REGION( 0x10000, "user3", 0 )
+	ROM_LOAD( "x000588p.u66",   0x00000, 0x10000, CRC(baa448cc) SHA1(0f1da407304f7dafbe06119d068f7caf99404cb4) ) /* Joker Poker - 10/31/94   @ IGT  L94-2068 */
+
+	ROM_REGION( 0x10000, "user4", 0 )
+	ROM_LOAD( "x000515p.u66",   0x00000, 0x10000, CRC(4311224a) SHA1(69e6657dacd6e09c2d1514417994adc561f63a83) ) /* Double Bonus Poker - 03/08/95   @ IGT  L95-0748 */
+
+	ROM_REGION( 0x10000, "user5", 0 )
+	ROM_LOAD( "x002037p.u66",   0x00000, 0x10000, CRC(12aea90e) SHA1(26ff0e7b81271252573739f26db9d20f35af274b) ) /* Nevada Bonus Poker */
+
+	ROM_REGION( 0x040000, "gfx1", 0 )
+	ROM_LOAD( "mro-cg2298.u77",  0x00000, 0x10000, CRC(8c35dc7f) SHA1(90e9566e816287e6248d7cab318dee3ad6fac871) )
+	ROM_LOAD( "mgo-cg2298.u78",  0x10000, 0x10000, CRC(3663174a) SHA1(c203a4a59f6bc1625d47f35426ffc5b4d279251a) )
+	ROM_LOAD( "mbo-cg2298.u79",  0x20000, 0x10000, CRC(9088cdbe) SHA1(dc62951c584463a1e795a774f5752f890d8e3f65) )
+	ROM_LOAD( "mxo-cg2298.u80",  0x30000, 0x10000, CRC(8d3aafc8) SHA1(931bc82398b94c63ed9f6f1bd95723aa801894cc) )
+
+	ROM_REGION( 0x200, "proms", 0 )
+	ROM_LOAD( "capx2298.u43", 0x0000, 0x0200, CRC(77856036) SHA1(820487c8494965408402ddee6a54511906218e66) )
+ROM_END
+
+ROM_START( pexmp013 ) /* Superboard : 5-in-1 Wingboard (XMP00013) Program in Spanish - PSR Verified */
 	ROM_REGION( 0x10000, "maincpu", 0 )
 	ROM_LOAD( "xmp00013.u67",   0x00000, 0x10000, CRC(76ca7c2b) SHA1(cdcbfc648d007362bb50541e6415354c07815d66) )
 
@@ -13790,34 +13840,7 @@ The CG2346 set seems to support all games supported in CG2298 as well as graphic
 	ROM_LOAD( "capx2346.u43", 0x0000, 0x0200, CRC(8df8ad29) SHA1(2d6a598fdc4290abe83a3d95c0ec8da6eb0f0e84) )
 ROM_END
 
-ROM_START( pexmp017 ) /* Superboard : 5-in-1 Wingboard (XMP00017) */
-/*
-
-Known Wingboard compatible program roms:
-   XMP00007 (CG2298+CAPX2298 - not dumped)
-   XMP00009 (CG2230+CAPX2230 - not dumped - MGM exclusive)
-   XMP00011 (CG2298+CAPX2298 - not dumped)
-   XMP00013 - Spanish
-   XMP00014 - International (CG2352+CAPX2352 - not dumped)
-   XMP00017
-   XMP00022 - Spanish
-   XMP00026 - Spanish
-   XMP00030
-
-Wingboard programs are not compatible with:
- Lucky Deal Poker, Shockwave Poker, Ace$ Bonus Poker, Dealt Deuces Bonus, Barbaric Deuces, Pay the Ace (No Face)
- and many other "specialty" poker games.
-
-The CG2298 graphics can support the following XnnnnnnP Data game types (as displayed):
-
-  Bonus Poker, Bonus Poker Dlx, Crazy Eights, Deluxe Deuces, Deuces Joker, Deuces Bonus, Deuces Wild
-  Double Bonus, Double Deuces, Dbl Dbl Bonus, Double Joker, Jacks or Better, Joker Poker, Loose Deuces
-  Nevada Bonus, Nevada Draw, Odds & Ends, Full House Bonus, Royal Deuces, Sevens or Better, Tens or Better
-  Triple Bonus, Two Pair, White Hot Aces
-
-  Super Aces shows as just Bonus Poker, Triple Bonus Poker Plus shows as just Triple Bonus
-
-*/
+ROM_START( pexmp017 ) /* Superboard : 5-in-1 Wingboard (XMP00017) - PSR Verified */
 	ROM_REGION( 0x10000, "maincpu", 0 )
 	ROM_LOAD( "xmp00017.u67",   0x00000, 0x10000, CRC(129e6eaa) SHA1(1dd2b83a672a618f338b553a6cbd598b6d4ce672) ) /*  09/17/97   @ IGT  L97-2154  */
 
@@ -13882,13 +13905,7 @@ Same set of games as CG2298 but includes graphics for International currency.
 	ROM_LOAD( "capx2298.u43", 0x0000, 0x0200, CRC(77856036) SHA1(820487c8494965408402ddee6a54511906218e66) ) /* Wrong!! Should be CAPX2352 - However colors should be correct */
 ROM_END
 
-ROM_START( pexmp017b ) /* Superboard : 5-in-1 Wingboard (XMP00017) */
-/*
-
-The CG2426 set supersedes CG2298 and adds graphics support for the following XnnnnnnP Data game types (as displayed):
-  BlackJack Bonus, Tpl Dbl Bonus, Super Dbl Bonus
-
-*/
+ROM_START( pexmp017b ) /* Superboard : 5-in-1 Wingboard (XMP00017) - PSR originally states CG2298 but also commonly found with CG2426 */
 	ROM_REGION( 0x10000, "maincpu", 0 )
 	ROM_LOAD( "xmp00017.u67",   0x00000, 0x10000, CRC(129e6eaa) SHA1(1dd2b83a672a618f338b553a6cbd598b6d4ce672) ) /*  09/17/97   @ IGT  L97-2154  */
 
@@ -13917,7 +13934,7 @@ The CG2426 set supersedes CG2298 and adds graphics support for the following Xnn
 	ROM_LOAD( "capx2298.u43", 0x0000, 0x0200, CRC(77856036) SHA1(820487c8494965408402ddee6a54511906218e66) )
 ROM_END
 
-ROM_START( pexmp022 ) /* Superboard : 5-in-1 Wingboard (XMP00022) Program in Spanish, Requires Spanish Wingboard CG rom set */
+ROM_START( pexmp022 ) /* Superboard : 5-in-1 Wingboard (XMP00022) Program in Spanish - PSR Verified */
 	ROM_REGION( 0x10000, "maincpu", 0 )
 	ROM_LOAD( "xmp00022.u67",   0x00000, 0x10000, CRC(ea21f38d) SHA1(d9712371e1286ed5957a71a14d868b78f741388d) )
 
@@ -13946,7 +13963,7 @@ ROM_START( pexmp022 ) /* Superboard : 5-in-1 Wingboard (XMP00022) Program in Spa
 	ROM_LOAD( "capx2346.u43", 0x0000, 0x0200, CRC(8df8ad29) SHA1(2d6a598fdc4290abe83a3d95c0ec8da6eb0f0e84) )
 ROM_END
 
-ROM_START( pexmp026 ) /* Superboard : 5-in-1 Wingboard (XMP00026) Program in Spanish, Requires Spanish Wingboard CG rom set */
+ROM_START( pexmp026 ) /* Superboard : 5-in-1 Wingboard (XMP00026) Program in Spanish - PSR Verified */
 	ROM_REGION( 0x10000, "maincpu", 0 )
 	ROM_LOAD( "xmp00026.u67",   0x00000, 0x10000, CRC(0b82387f) SHA1(8348c586cf692c5cbecfe7b52a4271e5aec55027) )
 
@@ -13976,12 +13993,6 @@ ROM_START( pexmp026 ) /* Superboard : 5-in-1 Wingboard (XMP00026) Program in Spa
 ROM_END
 
 ROM_START( pexmp030 ) /* Superboard : 5-in-1 Wingboard (XMP00030) - PSR Verified */
-/*
-
-The CG2451 set supersedes CG2298 & CG2426 and adds graphics support for the following XnnnnnnP Data game types (as displayed):
-  Dbl Dbl Bonus Plus
-
-*/
 	ROM_REGION( 0x10000, "maincpu", 0 )
 	ROM_LOAD( "xmp00030.u67",   0x00000, 0x10000, CRC(da3fcb6f) SHA1(114e581e5ebb5c40c3f3da2784122d3281f269ee) ) /*  11/12/00   @ IGT  L01-0197  */
 
@@ -13989,13 +14000,13 @@ The CG2451 set supersedes CG2298 & CG2426 and adds graphics support for the foll
 	ROM_LOAD( "x002377p.u66",   0x00000, 0x10000, CRC(541320d2) SHA1(670b17432e994fe1937091e5e96e1d58b9afbf29) ) /* Super Double Bonus Poker */
 
 	ROM_REGION( 0x10000, "user2", 0 )
-	ROM_LOAD( "x002111p.u66",   0x00000, 0x10000, CRC(f19dd63e) SHA1(0fe16cd0c75a9759e34bf95ce428e5b2da236215) ) /* 4 of a Kind Bonus Poker with Sequential Royal Flush */
+	ROM_LOAD( "x002111p.u66",   0x00000, 0x10000, CRC(f19dd63e) SHA1(0fe16cd0c75a9759e34bf95ce428e5b2da236215) ) /* 4 of a Kind Bonus Poker with Sequential Royal Flush - 01/17/96   @ IGT  L96-0184 */
 
 	ROM_REGION( 0x10000, "user3", 0 )
 	ROM_LOAD( "x000455p.u66",   0x00000, 0x10000, CRC(4992c51f) SHA1(8c70c59bdb16feba438230b30765076cebd44b53) ) /* Joker Poker */
 
 	ROM_REGION( 0x10000, "user4", 0 )
-	ROM_LOAD( "x000006p.u66",   0x00000, 0x10000, CRC(0ee609a1) SHA1(57043ac2c6ff4377479dd7b66d7e379053f3f602) ) /* Standard Draw Poker */
+	ROM_LOAD( "x000006p.u66",   0x00000, 0x10000, CRC(0ee609a1) SHA1(57043ac2c6ff4377479dd7b66d7e379053f3f602) ) /* Standard Draw Poker - 03/23/95   @ IGT  L95-0826 */
 
 	ROM_REGION( 0x10000, "user5", 0 )
 	ROM_LOAD( "x002474p.u66",   0x00000, 0x10000, CRC(74cc1423) SHA1(0522cee3a7e123ce51739c69f38915ca92bd03e5) ) /* Double Double Bonus Plus */
@@ -14563,6 +14574,7 @@ GAMEL(1995, pexm009p,  0,        peplus,  peplus_poker, peplus_state, peplussb,
 GAMEL(1995, pexm013p,  0,        peplus,  peplus_poker, peplus_state, peplussb, ROT0,  "IGT - International Game Technology", "Player's Edge Plus (XM00013P+XMP00025) Multi-Poker",        0, layout_pe_poker )
 
 /* Superboard : Multi-Poker (Wingboard) */
+GAMEL(1995, pexmp011,  0,        peplus,  peplus_poker, peplus_state, peplussbw,ROT0,  "IGT - International Game Technology", "Player's Edge Plus (XMP00011) 5-in-1 Wingboard (CG2298)",   0, layout_pe_poker )
 GAMEL(1995, pexmp013,  0,        peplus,  peplus_poker, peplus_state, peplussbw,ROT0,  "IGT - International Game Technology", "Player's Edge Plus (XMP00013) 5-in-1 Wingboard (CG2346) - Spanish", 0, layout_pe_poker )
 GAMEL(1995, pexmp017,  0,        peplus,  peplus_poker, peplus_state, peplussbw,ROT0,  "IGT - International Game Technology", "Player's Edge Plus (XMP00017) 5-in-1 Wingboard (CG2298)",   0, layout_pe_poker )
 GAMEL(1995, pexmp017a, pexmp017, peplus,  peplus_poker, peplus_state, peplussbw,ROT0,  "IGT - International Game Technology", "Player's Edge Plus (XMP00017) 5-in-1 Wingboard (CG2352)",   0, layout_pe_poker )
diff --git a/src/mame/drivers/pg685.cpp b/src/mame/drivers/pg685.cpp
index bf5c490..8cfbfa7 100644
--- a/src/mame/drivers/pg685.cpp
+++ b/src/mame/drivers/pg685.cpp
@@ -105,7 +105,10 @@ public:
 		m_maincpu(*this, "maincpu"),
 		m_vram(*this, "framebuffer"),
 		m_vram16(*this, "framebuffer16"),
-		m_fontram(*this, "charcopy")
+		m_fontram(*this, "charcopy"),
+		m_fdc(*this, "fdc"),
+		m_floppy0(*this, "fdc:0"),
+		m_floppy1(*this, "fdc:1")
 		{ }
 
 	MC6845_UPDATE_ROW(crtc_update_row);
@@ -122,6 +125,8 @@ public:
 	DECLARE_READ8_MEMBER(f9f78_r);
 	DECLARE_WRITE8_MEMBER(f9f78_w);
 	DECLARE_WRITE8_MEMBER(f9f79_w);
+	DECLARE_WRITE_LINE_MEMBER(fdc_drq_w);
+	DECLARE_WRITE_LINE_MEMBER(fdc_intrq_w);
 
 private:
 	virtual void machine_reset() override;
@@ -130,6 +135,9 @@ private:
 	optional_shared_ptr<uint8_t> m_vram;
 	optional_shared_ptr<uint16_t> m_vram16;
 	optional_shared_ptr<uint8_t> m_fontram;
+	required_device<fd1797_t> m_fdc;
+	required_device<floppy_connector> m_floppy0;
+	optional_device<floppy_connector> m_floppy1;
 };
 
 //**************************************************************************
@@ -147,7 +155,7 @@ static ADDRESS_MAP_START(pg675_mem, AS_PROGRAM, 8, pg685_state)
 	AM_RANGE(0xf9f06, 0xf9f07) AM_DEVREADWRITE("mainpic", pic8259_device, read, write)
 	AM_RANGE(0xf9f08, 0xf9f08) AM_DEVREADWRITE("mainuart", i8251_device, data_r, data_w)
 	AM_RANGE(0xf9f09, 0xf9f09) AM_DEVREADWRITE("mainuart", i8251_device, status_r, control_w)
-	AM_RANGE(0xf9f20, 0xf9f23) AM_DEVREADWRITE("fdc", wd2797_t, read, write)
+	AM_RANGE(0xf9f20, 0xf9f23) AM_DEVREADWRITE("fdc", fd1797_t, read, write)
 	AM_RANGE(0xf9f24, 0xf9f24) AM_READWRITE(f9f24_r, f9f24_w)
 	AM_RANGE(0xf9f28, 0xf9f2b) AM_DEVREADWRITE("modppi1", i8255_device, read, write)
 	AM_RANGE(0xf9f2c, 0xf9f2f) AM_DEVREADWRITE("modppi2", i8255_device, read, write)
@@ -183,7 +191,7 @@ static ADDRESS_MAP_START(pg685oua12_mem, AS_PROGRAM, 16, pg685_state)
 	AM_RANGE(0xf9f06, 0xf9f07) AM_DEVREADWRITE8("mainpic", pic8259_device, read, write, 0xffff)
 	AM_RANGE(0xf9f08, 0xf9f09) AM_DEVREADWRITE8("mainuart", i8251_device, data_r, data_w, 0x00ff)
 	AM_RANGE(0xf9f08, 0xf9f09) AM_DEVREADWRITE8("mainuart", i8251_device, status_r, control_w, 0xff00)
-	AM_RANGE(0xf9f20, 0xf9f23) AM_DEVREADWRITE8("fdc", wd2797_t, read, write, 0xffff)
+	AM_RANGE(0xf9f20, 0xf9f23) AM_DEVREADWRITE8("fdc", fd1797_t, read, write, 0xffff)
 	AM_RANGE(0xf9f24, 0xf9f25) AM_READWRITE8(f9f24_r, f9f24_w, 0x00ff)
 	AM_RANGE(0xf9f28, 0xf9f2b) AM_DEVREADWRITE8("modppi1", i8255_device, read, write, 0xffff)
 	AM_RANGE(0xf9f2c, 0xf9f2f) AM_DEVREADWRITE8("modppi2", i8255_device, read, write, 0xffff)
@@ -256,6 +264,15 @@ READ8_MEMBER(pg685_state::f9f3f_r)
 //  FLOPPY
 //**************************************************************************
 
+static SLOT_INTERFACE_START( pg675_floppies )
+	SLOT_INTERFACE( "525dd", FLOPPY_525_DD )
+SLOT_INTERFACE_END
+
+static SLOT_INTERFACE_START( pg685_floppies )
+	SLOT_INTERFACE( "525qd", FLOPPY_525_QD )
+SLOT_INTERFACE_END
+
+
 READ8_MEMBER(pg685_state::f9f24_r)
 {
 	logerror("Reading from F9F24\n");
@@ -267,6 +284,7 @@ WRITE8_MEMBER(pg685_state::f9f24_w)
 	logerror("Writing %02X to F9F24\n", data);
 }
 
+
 //**************************************************************************
 //  HARDDISK
 //**************************************************************************
@@ -370,7 +388,7 @@ static MACHINE_CONFIG_FRAGMENT(pg685_backplane)
 MACHINE_CONFIG_END
 
 static MACHINE_CONFIG_FRAGMENT(pg685_module)
-	MCFG_DEVICE_ADD("fdc", WD2797, XTAL_4MHz / 2) // divider guessed
+	MCFG_DEVICE_ADD("fdc", FD1797, XTAL_4MHz / 2) // divider guessed
 	MCFG_WD_FDC_INTRQ_CALLBACK(DEVWRITELINE("mainpic", pic8259_device, ir4_w))
 
 	MCFG_DEVICE_ADD("modppi1", I8255, 0)
@@ -379,6 +397,7 @@ static MACHINE_CONFIG_FRAGMENT(pg685_module)
 	MCFG_DEVICE_ADD("moduart", I8251, XTAL_4MHz / 2) // divider guessed
 
 	MCFG_DEVICE_ADD("rtc", MM58167, XTAL_32_768kHz)
+
 MACHINE_CONFIG_END
 
 static MACHINE_CONFIG_START( pg675, pg685_state )
@@ -419,6 +438,12 @@ static MACHINE_CONFIG_START( pg675, pg685_state )
 	// printer
 
 	// floppy
+	// MCFG_WD_FDC_INTRQ_CALLBACK(WRITELINE(zorba_state, fdc_intrq_w))
+	// MCFG_WD_FDC_DRQ_CALLBACK(WRITELINE(zorba_state, fdc_drq_w))
+	MCFG_FLOPPY_DRIVE_ADD("fdc:0", pg675_floppies, "525dd", floppy_image_device::default_floppy_formats)
+	MCFG_FLOPPY_DRIVE_SOUND(true)
+	MCFG_FLOPPY_DRIVE_ADD("fdc:1", pg675_floppies, "525dd", floppy_image_device::default_floppy_formats)
+	MCFG_FLOPPY_DRIVE_SOUND(true)
 
 MACHINE_CONFIG_END
 
@@ -462,6 +487,10 @@ static MACHINE_CONFIG_START( pg685, pg685_state )
 
 	// floppy
 
+	// MCFG_WD_FDC_DRQ_CALLBACK(WRITELINE(zorba_state, fdc_drq_w))
+	MCFG_FLOPPY_DRIVE_ADD("fdc:0", pg685_floppies, "525qd", floppy_image_device::default_floppy_formats)
+	MCFG_FLOPPY_DRIVE_SOUND(true)
+
 	// harddisk
 	MCFG_DEVICE_ADD("hdc", WD2010, XTAL_10MHz / 2) // divider guessed
 	MCFG_WD2010_OUT_INTRQ_CB(DEVWRITELINE("mainpic", pic8259_device, ir3_w))
@@ -507,6 +536,10 @@ static MACHINE_CONFIG_START( pg685oua12, pg685_state )
 
 	// floppy
 
+	// MCFG_WD_FDC_DRQ_CALLBACK(WRITELINE(zorba_state, fdc_drq_w))
+	MCFG_FLOPPY_DRIVE_ADD("fdc:0", pg685_floppies, "525qd", floppy_image_device::default_floppy_formats)
+	MCFG_FLOPPY_DRIVE_SOUND(true)
+
 	// harddisk
 	MCFG_DEVICE_ADD("hdc", WD2010, XTAL_10MHz / 2) // divider guessed
 	MCFG_WD2010_OUT_INTRQ_CB(DEVWRITELINE("mainpic", pic8259_device, ir3_w))
diff --git a/src/mame/drivers/pgm2.cpp b/src/mame/drivers/pgm2.cpp
index 813d01a..e276dc2 100644
--- a/src/mame/drivers/pgm2.cpp
+++ b/src/mame/drivers/pgm2.cpp
@@ -550,18 +550,18 @@ DRIVER_INIT_MEMBER(pgm2_state,kov3)
 GAME( 2007, orleg2,       0,         pgm2,    pgm2, pgm2_state,     orleg2,       ROT0, "IGS", "Oriental Legend 2 (V104, China)", MACHINE_IS_SKELETON )
 GAME( 2007, orleg2o,      orleg2,    pgm2,    pgm2, pgm2_state,     orleg2,       ROT0, "IGS", "Oriental Legend 2 (V103, China)", MACHINE_IS_SKELETON )
 GAME( 2007, orleg2oa,     orleg2,    pgm2,    pgm2, pgm2_state,     orleg2,       ROT0, "IGS", "Oriental Legend 2 (V101, China)", MACHINE_IS_SKELETON )
-// should be earlier verisons too.
+// should be earlier versions too.
 
 GAME( 2008, kov2nl,       0,         pgm2,    pgm2, pgm2_state,     kov2nl,       ROT0, "IGS", "Knights of Valour 2 New Legend (V302, China)", MACHINE_IS_SKELETON )
 GAME( 2008, kov2nlo,      kov2nl,    pgm2,    pgm2, pgm2_state,     kov2nl,       ROT0, "IGS", "Knights of Valour 2 New Legend (V301, China)", MACHINE_IS_SKELETON )
 GAME( 2008, kov2nloa,     kov2nl,    pgm2,    pgm2, pgm2_state,     kov2nl,       ROT0, "IGS", "Knights of Valour 2 New Legend (V300, Taiwan)", MACHINE_IS_SKELETON )
-// should be earlier verisons too.
+// should be earlier versions too.
 
 GAME( 2010, ddpdojh,      0,    pgm2,    pgm2, pgm2_state,     ddpdojh,    ROT270, "IGS", "Dodonpachi Daioujou Tamashii (V201, China)", MACHINE_IS_SKELETON )
-// should be earlier verisons too.
+// should be earlier versions too.
 
 GAME( 2011, kov3,         0,    pgm2,    pgm2, pgm2_state,     kov3,       ROT0, "IGS", "Knights of Valour 3 (V102, China)", MACHINE_IS_SKELETON )
-// should be earlier verisons too.
+// should be earlier versions too.
 
 // The King of Fighters '98 - Ultimate Match - Hero
 // Jigsaw World Arena
diff --git a/src/mame/drivers/pgm3.cpp b/src/mame/drivers/pgm3.cpp
new file mode 100644
index 0000000..218dd68
--- /dev/null
+++ b/src/mame/drivers/pgm3.cpp
@@ -0,0 +1,174 @@
+// license:BSD-3-Clause
+// copyright-holders:Xing Xing
+
+/* PGM 3 hardware.
+
+  Games on this platform
+
+  Knights of Valour 3 HD
+
+  according to Xing Xing
+  "The main cpu of PGM3 whiched coded as 'SOC38' is an ARM1176 at 800M designed by SOCLE(http://www.socle-tech.com/). Not much infomation is available on this asic"
+
+  there is likely a 512KBytes encrypted bootloader(u-boot?) inside the cpu which load the kernel&initrd from the external SD card.
+
+  however, according to
+  http://www.arcadebelgium.net/t4958-knights-of-valour-3-hd-sangoku-senki-3-hd
+  the CPU is an Intel Atom D525 CPU with 2GB of RAM (but based on hardware images this is incorrect, they clearly show the CPU Xing Xing states is used)
+
+
+  the card images (except v105) seem to have encrypted data up to the C2000000 mark, then
+  some text string about a non-bootable disk followed by mostly blank data
+
+  Offset(h)  00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+
+0C2000000  EB 3C 90 6D 6B 64 6F 73 66 73 00 00 02 04 04 00  ë<.mkdosfs......
+0C2000010  02 00 02 00 00 F8 00 01 3F 00 FF 00 00 00 00 00  .....ø..?.ÿ.....
+0C2000020  00 00 04 00 00 00 29 4C 88 BA 7C 20 20 20 20 20  ......)L.º|
+0C2000030  20 20 20 20 20 20 46 41 54 31 36 20 20 20 0E 1F        FAT16   ..
+0C2000040  BE 5B 7C AC 22 C0 74 0B 56 B4 0E BB 07 00 CD 10  ¾[|¬"Àt.V´.»..Í.
+0C2000050  5E EB F0 32 E4 CD 16 CD 19 EB FE 54 68 69 73 20  ^ëð2äÍ.Í.ëþThis
+0C2000060  69 73 20 6E 6F 74 20 61 20 62 6F 6F 74 61 62 6C  is not a bootabl
+0C2000070  65 20 64 69 73 6B 2E 20 20 50 6C 65 61 73 65 20  e disk.  Please
+0C2000080  69 6E 73 65 72 74 20 61 20 62 6F 6F 74 61 62 6C  insert a bootabl
+0C2000090  65 20 66 6C 6F 70 70 79 20 61 6E 64 0D 0A 70 72  e floppy and..pr
+0C20000A0  65 73 73 20 61 6E 79 20 6B 65 79 20 74 6F 20 74  ess any key to t
+0C20000B0  72 79 20 61 67 61 69 6E 20 2E 2E 2E 20 0D 0A 00  ry again ... ...
+
+  the v105 image has the encrypted data starting at 400000 and the above at C2400000
+  and is overall slightly shorter.  it was probably dumped using a different method?
+  assuming one is the correct method the others will need adjusting.
+
+
+  DSW:
+    1: OFF = Game mode / ON = Test mode
+    2: OFF = JAMMA / ON = JVS
+    3: OFF = 16/9 (1280x720) / ON = 4/3 (800x600)
+    4: NO USE
+
+  todo: add other hardware details?
+
+*/
+
+#include "emu.h"
+#include "cpu/arm7/arm7.h"
+#include "cpu/arm7/arm7core.h"
+
+
+class pgm3_state : public driver_device
+{
+public:
+	pgm3_state(const machine_config &mconfig, device_type type, const char *tag)
+		: driver_device(mconfig, type, tag),
+		m_maincpu(*this, "maincpu") { }
+
+	DECLARE_DRIVER_INIT(kov3hd);
+
+	virtual void machine_start() override;
+	virtual void machine_reset() override;
+	virtual void video_start() override;
+	uint32_t screen_update_pgm3(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
+	void screen_eof_pgm3(screen_device &screen, bool state);
+	required_device<cpu_device> m_maincpu;
+};
+
+static ADDRESS_MAP_START( pgm3_map, AS_PROGRAM, 32, pgm3_state )
+	AM_RANGE(0x00000000, 0x00003fff) AM_ROM
+ADDRESS_MAP_END
+
+static INPUT_PORTS_START( pgm3 )
+INPUT_PORTS_END
+
+uint32_t pgm3_state::screen_update_pgm3(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
+{
+	return 0;
+}
+
+void pgm3_state::screen_eof_pgm3(screen_device &screen, bool state)
+{
+}
+
+void pgm3_state::video_start()
+{
+}
+
+void pgm3_state::machine_start()
+{
+}
+
+void pgm3_state::machine_reset()
+{
+}
+
+static MACHINE_CONFIG_START( pgm3, pgm3_state )
+
+	/* basic machine hardware */
+	MCFG_CPU_ADD("maincpu", ARM9, 800000000) // wrong, see notes at top of driver
+	MCFG_CPU_PROGRAM_MAP(pgm3_map)
+	MCFG_DEVICE_DISABLE()
+
+	/* video hardware */
+	MCFG_SCREEN_ADD("screen", RASTER)
+	MCFG_SCREEN_REFRESH_RATE(60)
+	MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
+	MCFG_SCREEN_SIZE(1280, 720)
+	MCFG_SCREEN_VISIBLE_AREA(0, 1280-1, 0, 720-1)
+	MCFG_SCREEN_UPDATE_DRIVER(pgm3_state, screen_update_pgm3)
+	MCFG_SCREEN_VBLANK_DRIVER(pgm3_state, screen_eof_pgm3)
+	MCFG_SCREEN_PALETTE("palette")
+
+	MCFG_PALETTE_ADD("palette", 0x1000)
+MACHINE_CONFIG_END
+
+ROM_START( kov3hd )
+	ROM_REGION( 0x04000, "maincpu", ROMREGION_ERASE00 )
+	// does it boot from the card, or is there an internal rom?
+
+	DISK_REGION( "card" )
+	DISK_IMAGE( "kov3hd_v105", 0, SHA1(c185888c59880805bb76b5c0a42b05c614dcff37) )
+ROM_END
+
+ROM_START( kov3hd104 )
+	ROM_REGION( 0x04000, "maincpu", ROMREGION_ERASE00 )
+	// does it boot from the card, or is there an internal rom?
+
+	DISK_REGION( "card" )
+	DISK_IMAGE( "kov3hd_m104", 0, SHA1(899b3b81825e6f23ae8f39aa67ad5b019f387cf9) )
+ROM_END
+
+ROM_START( kov3hd103 )
+	ROM_REGION( 0x04000, "maincpu", ROMREGION_ERASE00 )
+	// does it boot from the card, or is there an internal rom?
+
+	DISK_REGION( "card" )
+	DISK_IMAGE( "kov3hd_m103", 0, SHA1(0d4fd981f477cd5ed62609b875f4ddec939a2bb0) )
+ROM_END
+
+ROM_START( kov3hd102 )
+	ROM_REGION( 0x04000, "maincpu", ROMREGION_ERASE00 )
+	// does it boot from the card, or is there an internal rom?
+
+	DISK_REGION( "card" )
+	DISK_IMAGE( "kov3hd_m102", 0, SHA1(a5a872f9add5527b94019ec77ff1cd0f167f040f) )
+ROM_END
+
+ROM_START( kov3hd101 )
+	ROM_REGION( 0x04000, "maincpu", ROMREGION_ERASE00 )
+	// does it boot from the card, or is there an internal rom?
+
+	DISK_REGION( "card" )
+	DISK_IMAGE( "kov3hd_m101", 0, SHA1(086d6f1b8b2c01a8670fd6480da44b9c507f6e08) )
+ROM_END
+
+
+DRIVER_INIT_MEMBER(pgm3_state,kov3hd)
+{
+}
+
+
+// all dumped sets might be China region, unless region info comes from elsewhere
+GAME( 2011, kov3hd,     0,      pgm3,    pgm3, pgm3_state,     kov3hd,       ROT0, "IGS", "Knights of Valour 3 HD (V105)", MACHINE_IS_SKELETON )
+GAME( 2011, kov3hd104,  kov3hd, pgm3,    pgm3, pgm3_state,     kov3hd,       ROT0, "IGS", "Knights of Valour 3 HD (V104)", MACHINE_IS_SKELETON )
+GAME( 2011, kov3hd103,  kov3hd, pgm3,    pgm3, pgm3_state,     kov3hd,       ROT0, "IGS", "Knights of Valour 3 HD (V103)", MACHINE_IS_SKELETON )
+GAME( 2011, kov3hd102,  kov3hd, pgm3,    pgm3, pgm3_state,     kov3hd,       ROT0, "IGS", "Knights of Valour 3 HD (V102)", MACHINE_IS_SKELETON )
+GAME( 2011, kov3hd101,  kov3hd, pgm3,    pgm3, pgm3_state,     kov3hd,       ROT0, "IGS", "Knights of Valour 3 HD (V101)", MACHINE_IS_SKELETON )
diff --git a/src/mame/drivers/photon.cpp b/src/mame/drivers/photon.cpp
index bf33abe..bd965a5 100644
--- a/src/mame/drivers/photon.cpp
+++ b/src/mame/drivers/photon.cpp
@@ -31,20 +31,24 @@ public:
 		: pk8000_base_state(mconfig, type, tag),
 		m_speaker(*this, "speaker") { }
 
-	DECLARE_WRITE8_MEMBER(pk8000_80_porta_w);
-	DECLARE_READ8_MEMBER(pk8000_80_portb_r);
-	DECLARE_WRITE8_MEMBER(pk8000_80_portc_w);
+	DECLARE_WRITE8_MEMBER(_80_porta_w);
+	DECLARE_READ8_MEMBER(_80_portb_r);
+	DECLARE_WRITE8_MEMBER(_80_portc_w);
+
 	virtual void machine_reset() override;
 	virtual void video_start() override;
-	uint32_t screen_update_photon(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
-	INTERRUPT_GEN_MEMBER(pk8000_interrupt);
-	IRQ_CALLBACK_MEMBER(pk8000_irq_callback);
-	void pk8000_set_bank(uint8_t data);
+
+	uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
+
+	INTERRUPT_GEN_MEMBER(interrupt);
+	IRQ_CALLBACK_MEMBER(irq_callback);
+	void set_bank(uint8_t data);
+
 	required_device<speaker_sound_device> m_speaker;
 };
 
 
-void photon_state::pk8000_set_bank(uint8_t data)
+void photon_state::set_bank(uint8_t data)
 {
 	uint8_t *rom = memregion("maincpu")->base();
 	uint8_t *ram = memregion("maincpu")->base();
@@ -103,17 +107,17 @@ void photon_state::pk8000_set_bank(uint8_t data)
 				break;
 	}
 }
-WRITE8_MEMBER(photon_state::pk8000_80_porta_w)
+WRITE8_MEMBER(photon_state::_80_porta_w)
 {
-	pk8000_set_bank(data);
+	set_bank(data);
 }
 
-READ8_MEMBER(photon_state::pk8000_80_portb_r)
+READ8_MEMBER(photon_state::_80_portb_r)
 {
 	return 0xff;
 }
 
-WRITE8_MEMBER(photon_state::pk8000_80_portc_w)
+WRITE8_MEMBER(photon_state::_80_portc_w)
 {
 	m_speaker->level_w(BIT(data,7));
 }
@@ -130,14 +134,14 @@ static ADDRESS_MAP_START( pk8000_io , AS_IO, 8, photon_state )
 	ADDRESS_MAP_UNMAP_HIGH
 	AM_RANGE(0x80, 0x83) AM_DEVREADWRITE("ppi8255_1", i8255_device, read, write)
 	AM_RANGE(0x84, 0x87) AM_DEVREADWRITE("ppi8255_2", i8255_device, read, write)
-	AM_RANGE(0x88, 0x88) AM_READWRITE(pk8000_video_color_r,pk8000_video_color_w)
+	AM_RANGE(0x88, 0x88) AM_READWRITE(video_color_r, video_color_w)
 	AM_RANGE(0x8c, 0x8c) AM_READ_PORT("JOY1")
 	AM_RANGE(0x8d, 0x8d) AM_READ_PORT("JOY2")
-	AM_RANGE(0x90, 0x90) AM_READWRITE(pk8000_text_start_r,pk8000_text_start_w)
-	AM_RANGE(0x91, 0x91) AM_READWRITE(pk8000_chargen_start_r,pk8000_chargen_start_w)
-	AM_RANGE(0x92, 0x92) AM_READWRITE(pk8000_video_start_r,pk8000_video_start_w)
-	AM_RANGE(0x93, 0x93) AM_READWRITE(pk8000_color_start_r,pk8000_color_start_w)
-	AM_RANGE(0xa0, 0xbf) AM_READWRITE(pk8000_color_r,pk8000_color_w)
+	AM_RANGE(0x90, 0x90) AM_READWRITE(text_start_r, text_start_w)
+	AM_RANGE(0x91, 0x91) AM_READWRITE(chargen_start_r, chargen_start_w)
+	AM_RANGE(0x92, 0x92) AM_READWRITE(video_start_r, video_start_w)
+	AM_RANGE(0x93, 0x93) AM_READWRITE(color_start_r, color_start_w)
+	AM_RANGE(0xa0, 0xbf) AM_READWRITE(color_r, color_w)
 ADDRESS_MAP_END
 
 static INPUT_PORTS_START( photon )
@@ -155,12 +159,12 @@ static INPUT_PORTS_START( photon )
 	PORT_BIT(0xff, IP_ACTIVE_HIGH, IPT_UNUSED)
 INPUT_PORTS_END
 
-INTERRUPT_GEN_MEMBER(photon_state::pk8000_interrupt)
+INTERRUPT_GEN_MEMBER(photon_state::interrupt)
 {
 	device.execute().set_input_line(0, HOLD_LINE);
 }
 
-IRQ_CALLBACK_MEMBER(photon_state::pk8000_irq_callback)
+IRQ_CALLBACK_MEMBER(photon_state::irq_callback)
 {
 	return 0xff;
 }
@@ -168,16 +172,24 @@ IRQ_CALLBACK_MEMBER(photon_state::pk8000_irq_callback)
 
 void photon_state::machine_reset()
 {
-	pk8000_set_bank(0);
+	set_bank(0);
 }
 
 void photon_state::video_start()
 {
+	save_item(NAME(m_text_start));
+	save_item(NAME(m_chargen_start));
+	save_item(NAME(m_video_start));
+	save_item(NAME(m_color_start));
+	save_item(NAME(m_video_mode));
+	save_item(NAME(m_video_color));
+	save_item(NAME(m_color));
+	save_item(NAME(m_video_enable));
 }
 
-uint32_t photon_state::screen_update_photon(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
+uint32_t photon_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
 {
-	return pk8000_video_update(screen, bitmap, cliprect, memregion("maincpu")->base());
+	return video_update(screen, bitmap, cliprect, memregion("maincpu")->base());
 }
 
 static MACHINE_CONFIG_START( photon, photon_state )
@@ -186,8 +198,8 @@ static MACHINE_CONFIG_START( photon, photon_state )
 	MCFG_CPU_ADD("maincpu",I8080, 1780000)
 	MCFG_CPU_PROGRAM_MAP(pk8000_mem)
 	MCFG_CPU_IO_MAP(pk8000_io)
-	MCFG_CPU_VBLANK_INT_DRIVER("screen", photon_state,  pk8000_interrupt)
-	MCFG_CPU_IRQ_ACKNOWLEDGE_DRIVER(photon_state,pk8000_irq_callback)
+	MCFG_CPU_VBLANK_INT_DRIVER("screen", photon_state, interrupt)
+	MCFG_CPU_IRQ_ACKNOWLEDGE_DRIVER(photon_state, irq_callback)
 
 	/* video hardware */
 	MCFG_SCREEN_ADD("screen", RASTER)
@@ -195,21 +207,21 @@ static MACHINE_CONFIG_START( photon, photon_state )
 	MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */
 	MCFG_SCREEN_SIZE(256+32, 192+32)
 	MCFG_SCREEN_VISIBLE_AREA(0, 256+32-1, 0, 192+32-1)
-	MCFG_SCREEN_UPDATE_DRIVER(photon_state, screen_update_photon)
+	MCFG_SCREEN_UPDATE_DRIVER(photon_state, screen_update)
 	MCFG_SCREEN_PALETTE("palette")
 
 	MCFG_PALETTE_ADD("palette", 16)
 	MCFG_PALETTE_INIT_OWNER(pk8000_base_state, pk8000)
 
 	MCFG_DEVICE_ADD("ppi8255_1", I8255, 0)
-	MCFG_I8255_OUT_PORTA_CB(WRITE8(photon_state, pk8000_80_porta_w))
-	MCFG_I8255_IN_PORTB_CB(READ8(photon_state, pk8000_80_portb_r))
-	MCFG_I8255_OUT_PORTC_CB(WRITE8(photon_state, pk8000_80_portc_w))
+	MCFG_I8255_OUT_PORTA_CB(WRITE8(photon_state, _80_porta_w))
+	MCFG_I8255_IN_PORTB_CB(READ8(photon_state, _80_portb_r))
+	MCFG_I8255_OUT_PORTC_CB(WRITE8(photon_state, _80_portc_w))
 
 	MCFG_DEVICE_ADD("ppi8255_2", I8255, 0)
-	MCFG_I8255_IN_PORTA_CB(READ8(pk8000_base_state, pk8000_84_porta_r))
-	MCFG_I8255_OUT_PORTA_CB(WRITE8(pk8000_base_state, pk8000_84_porta_w))
-	MCFG_I8255_OUT_PORTC_CB(WRITE8(pk8000_base_state, pk8000_84_portc_w))
+	MCFG_I8255_IN_PORTA_CB(READ8(pk8000_base_state, _84_porta_r))
+	MCFG_I8255_OUT_PORTA_CB(WRITE8(pk8000_base_state, _84_porta_w))
+	MCFG_I8255_OUT_PORTC_CB(WRITE8(pk8000_base_state, _84_portc_w))
 
 	/* audio hardware */
 	MCFG_SPEAKER_STANDARD_MONO("mono")
diff --git a/src/mame/drivers/pipeline.cpp b/src/mame/drivers/pipeline.cpp
index ac50b77..f86d023 100644
--- a/src/mame/drivers/pipeline.cpp
+++ b/src/mame/drivers/pipeline.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /*
 PCB Layout
diff --git a/src/mame/drivers/pitnrun.cpp b/src/mame/drivers/pitnrun.cpp
index 6c2d6d7..48892f5 100644
--- a/src/mame/drivers/pitnrun.cpp
+++ b/src/mame/drivers/pitnrun.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina, Pierpaolo Prazzoli
 /****************************************************
    Pit&Run - Taito 1984
diff --git a/src/mame/drivers/pk8000.cpp b/src/mame/drivers/pk8000.cpp
index 7560ab6..35d0a12 100644
--- a/src/mame/drivers/pk8000.cpp
+++ b/src/mame/drivers/pk8000.cpp
@@ -40,21 +40,25 @@ public:
 		, m_bank8(*this, "bank8")
 		, m_io_joy1(*this, "JOY1")
 		, m_io_joy2(*this, "JOY2")
+		, m_keyboard(*this, "LINE%u", 0)
 	{ }
 
 	uint8_t m_keyboard_line;
-	DECLARE_READ8_MEMBER(pk8000_joy_1_r);
-	DECLARE_READ8_MEMBER(pk8000_joy_2_r);
+
+	DECLARE_READ8_MEMBER(joy_1_r);
+	DECLARE_READ8_MEMBER(joy_2_r);
+	DECLARE_WRITE8_MEMBER(_80_porta_w);
+	DECLARE_READ8_MEMBER(_80_portb_r);
+	DECLARE_WRITE8_MEMBER(_80_portc_w);
+
 	virtual void machine_start() override;
 	virtual void machine_reset() override;
 	virtual void video_start() override;
-	uint32_t screen_update_pk8000(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
-	INTERRUPT_GEN_MEMBER(pk8000_interrupt);
-	DECLARE_WRITE8_MEMBER(pk8000_80_porta_w);
-	DECLARE_READ8_MEMBER(pk8000_80_portb_r);
-	DECLARE_WRITE8_MEMBER(pk8000_80_portc_w);
 
-	IRQ_CALLBACK_MEMBER(pk8000_irq_callback);
+	uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
+
+	INTERRUPT_GEN_MEMBER(interrupt);
+	IRQ_CALLBACK_MEMBER(irq_callback);
 
 protected:
 	required_device<cpu_device> m_maincpu;
@@ -72,14 +76,14 @@ protected:
 	required_memory_bank m_bank8;
 	required_ioport m_io_joy1;
 	required_ioport m_io_joy2;
-	ioport_port *m_io_port[10];
+	required_ioport_array<10> m_keyboard;
 
-	void pk8000_set_bank(uint8_t data);
+	void set_bank(uint8_t data);
 };
 
 
 
-void pk8000_state::pk8000_set_bank(uint8_t data)
+void pk8000_state::set_bank(uint8_t data)
 {
 	uint8_t *rom = m_region_maincpu->base();
 	uint8_t *ram = m_ram->pointer();
@@ -138,20 +142,20 @@ void pk8000_state::pk8000_set_bank(uint8_t data)
 				break;
 	}
 }
-WRITE8_MEMBER(pk8000_state::pk8000_80_porta_w)
+WRITE8_MEMBER(pk8000_state::_80_porta_w)
 {
-	pk8000_set_bank(data);
+	set_bank(data);
 }
 
-READ8_MEMBER(pk8000_state::pk8000_80_portb_r)
+READ8_MEMBER(pk8000_state::_80_portb_r)
 {
 	if(m_keyboard_line>9) {
 		return 0xff;
 	}
-	return m_io_port[m_keyboard_line]->read();
+	return m_keyboard[m_keyboard_line]->read();
 }
 
-WRITE8_MEMBER(pk8000_state::pk8000_80_portc_w)
+WRITE8_MEMBER(pk8000_state::_80_portc_w)
 {
 	m_keyboard_line = data & 0x0f;
 
@@ -161,13 +165,13 @@ WRITE8_MEMBER(pk8000_state::pk8000_80_portc_w)
 	m_cassette->output((BIT(data, 6)) ? +1.0 : 0.0);
 }
 
-READ8_MEMBER(pk8000_state::pk8000_joy_1_r)
+READ8_MEMBER(pk8000_state::joy_1_r)
 {
 	uint8_t retVal = (m_cassette->input() > 0.0038 ? 0x80 : 0);
 	retVal |= m_io_joy1->read() & 0x7f;
 	return retVal;
 }
-READ8_MEMBER(pk8000_state::pk8000_joy_2_r)
+READ8_MEMBER(pk8000_state::joy_2_r)
 {
 	uint8_t retVal = (m_cassette->input() > 0.0038 ? 0x80 : 0);
 	retVal |= m_io_joy2->read() & 0x7f;
@@ -186,14 +190,14 @@ static ADDRESS_MAP_START( pk8000_io , AS_IO, 8, pk8000_state )
 	ADDRESS_MAP_UNMAP_HIGH
 	AM_RANGE(0x80, 0x83) AM_DEVREADWRITE("ppi8255_1", i8255_device, read, write)
 	AM_RANGE(0x84, 0x87) AM_DEVREADWRITE("ppi8255_2", i8255_device, read, write)
-	AM_RANGE(0x88, 0x88) AM_READWRITE(pk8000_video_color_r,pk8000_video_color_w)
-	AM_RANGE(0x8c, 0x8c) AM_READ(pk8000_joy_1_r)
-	AM_RANGE(0x8d, 0x8d) AM_READ(pk8000_joy_2_r)
-	AM_RANGE(0x90, 0x90) AM_READWRITE(pk8000_text_start_r,pk8000_text_start_w)
-	AM_RANGE(0x91, 0x91) AM_READWRITE(pk8000_chargen_start_r,pk8000_chargen_start_w)
-	AM_RANGE(0x92, 0x92) AM_READWRITE(pk8000_video_start_r,pk8000_video_start_w)
-	AM_RANGE(0x93, 0x93) AM_READWRITE(pk8000_color_start_r,pk8000_color_start_w)
-	AM_RANGE(0xa0, 0xbf) AM_READWRITE(pk8000_color_r,pk8000_color_w)
+	AM_RANGE(0x88, 0x88) AM_READWRITE(video_color_r, video_color_w)
+	AM_RANGE(0x8c, 0x8c) AM_READ(joy_1_r)
+	AM_RANGE(0x8d, 0x8d) AM_READ(joy_2_r)
+	AM_RANGE(0x90, 0x90) AM_READWRITE(text_start_r, text_start_w)
+	AM_RANGE(0x91, 0x91) AM_READWRITE(chargen_start_r, chargen_start_w)
+	AM_RANGE(0x92, 0x92) AM_READWRITE(video_start_r, video_start_w)
+	AM_RANGE(0x93, 0x93) AM_READWRITE(color_start_r, color_start_w)
+	AM_RANGE(0xa0, 0xbf) AM_READWRITE(color_r, color_w)
 ADDRESS_MAP_END
 
 /*   Input ports */
@@ -308,12 +312,12 @@ static INPUT_PORTS_START( pk8000 )
 		PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_UNUSED)
 INPUT_PORTS_END
 
-INTERRUPT_GEN_MEMBER(pk8000_state::pk8000_interrupt)
+INTERRUPT_GEN_MEMBER(pk8000_state::interrupt)
 {
 	device.execute().set_input_line(0, HOLD_LINE);
 }
 
-IRQ_CALLBACK_MEMBER(pk8000_state::pk8000_irq_callback)
+IRQ_CALLBACK_MEMBER(pk8000_state::irq_callback)
 {
 	return 0xff;
 }
@@ -321,26 +325,29 @@ IRQ_CALLBACK_MEMBER(pk8000_state::pk8000_irq_callback)
 
 void pk8000_state::machine_start()
 {
-	static const char *const keynames[] = { "LINE0", "LINE1", "LINE2", "LINE3", "LINE4", "LINE5", "LINE6", "LINE7", "LINE8", "LINE9" };
-
-	for ( int i = 0; i < 10; i++ )
-	{
-		m_io_port[i] = ioport(keynames[i]);
-	}
+	save_item(NAME(m_keyboard_line));
 }
 
 void pk8000_state::machine_reset()
 {
-	pk8000_set_bank(0);
+	set_bank(0);
 }
 
 void pk8000_state::video_start()
 {
+	save_item(NAME(m_text_start));
+	save_item(NAME(m_chargen_start));
+	save_item(NAME(m_video_start));
+	save_item(NAME(m_color_start));
+	save_item(NAME(m_video_mode));
+	save_item(NAME(m_video_color));
+	save_item(NAME(m_color));
+	save_item(NAME(m_video_enable));
 }
 
-uint32_t pk8000_state::screen_update_pk8000(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
+uint32_t pk8000_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
 {
-	return pk8000_video_update(screen, bitmap, cliprect, m_ram->pointer());
+	return video_update(screen, bitmap, cliprect, m_ram->pointer());
 }
 
 static MACHINE_CONFIG_START( pk8000, pk8000_state )
@@ -348,8 +355,8 @@ static MACHINE_CONFIG_START( pk8000, pk8000_state )
 	MCFG_CPU_ADD("maincpu",I8080, 1780000)
 	MCFG_CPU_PROGRAM_MAP(pk8000_mem)
 	MCFG_CPU_IO_MAP(pk8000_io)
-	MCFG_CPU_VBLANK_INT_DRIVER("screen", pk8000_state,  pk8000_interrupt)
-	MCFG_CPU_IRQ_ACKNOWLEDGE_DRIVER(pk8000_state,pk8000_irq_callback)
+	MCFG_CPU_VBLANK_INT_DRIVER("screen", pk8000_state,  interrupt)
+	MCFG_CPU_IRQ_ACKNOWLEDGE_DRIVER(pk8000_state, irq_callback)
 
 	/* video hardware */
 	MCFG_SCREEN_ADD("screen", RASTER)
@@ -357,21 +364,21 @@ static MACHINE_CONFIG_START( pk8000, pk8000_state )
 	MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */
 	MCFG_SCREEN_SIZE(256+32, 192+32)
 	MCFG_SCREEN_VISIBLE_AREA(0, 256+32-1, 0, 192+32-1)
-	MCFG_SCREEN_UPDATE_DRIVER(pk8000_state, screen_update_pk8000)
+	MCFG_SCREEN_UPDATE_DRIVER(pk8000_state, screen_update)
 	MCFG_SCREEN_PALETTE("palette")
 
 	MCFG_PALETTE_ADD("palette", 16)
 	MCFG_PALETTE_INIT_OWNER(pk8000_base_state, pk8000)
 
 	MCFG_DEVICE_ADD("ppi8255_1", I8255, 0)
-	MCFG_I8255_OUT_PORTA_CB(WRITE8(pk8000_state, pk8000_80_porta_w))
-	MCFG_I8255_IN_PORTB_CB(READ8(pk8000_state, pk8000_80_portb_r))
-	MCFG_I8255_OUT_PORTC_CB(WRITE8(pk8000_state, pk8000_80_portc_w))
+	MCFG_I8255_OUT_PORTA_CB(WRITE8(pk8000_state, _80_porta_w))
+	MCFG_I8255_IN_PORTB_CB(READ8(pk8000_state, _80_portb_r))
+	MCFG_I8255_OUT_PORTC_CB(WRITE8(pk8000_state, _80_portc_w))
 
 	MCFG_DEVICE_ADD("ppi8255_2", I8255, 0)
-	MCFG_I8255_IN_PORTA_CB(READ8(pk8000_base_state, pk8000_84_porta_r))
-	MCFG_I8255_OUT_PORTA_CB(WRITE8(pk8000_base_state, pk8000_84_porta_w))
-	MCFG_I8255_OUT_PORTC_CB(WRITE8(pk8000_base_state,pk8000_84_portc_w))
+	MCFG_I8255_IN_PORTA_CB(READ8(pk8000_base_state, _84_porta_r))
+	MCFG_I8255_OUT_PORTA_CB(WRITE8(pk8000_base_state, _84_porta_w))
+	MCFG_I8255_OUT_PORTC_CB(WRITE8(pk8000_base_state, _84_portc_w))
 
 	/* audio hardware */
 	MCFG_SPEAKER_STANDARD_MONO("mono")
@@ -408,6 +415,6 @@ ROM_END
 /* Driver */
 
 /*    YEAR  NAME    PARENT  COMPAT   MACHINE    INPUT    INIT     COMPANY   FULLNAME       FLAGS */
-COMP( 1987, vesta,  0,       0,     pk8000,     pk8000, driver_device,   0,   "BP EVM",   "PK8000 Vesta",       0)
-COMP( 1987, hobby,  vesta,   0,     pk8000,     pk8000, driver_device,   0,   "BP EVM",   "PK8000 Sura/Hobby",  0)
-COMP( 1987, pk8002, vesta,   0,     pk8000,     pk8000, driver_device,   0,   "<unknown>",   "PK8002 Elf",  MACHINE_NOT_WORKING)
+COMP( 1987, vesta,  0,       0,     pk8000,     pk8000, driver_device,   0,   "BP EVM",   "PK8000 Vesta",       0 )
+COMP( 1987, hobby,  vesta,   0,     pk8000,     pk8000, driver_device,   0,   "BP EVM",   "PK8000 Sura/Hobby",  0 )
+COMP( 1987, pk8002, vesta,   0,     pk8000,     pk8000, driver_device,   0,   "<unknown>",   "PK8002 Elf",  MACHINE_NOT_WORKING )
diff --git a/src/mame/drivers/playmark.cpp b/src/mame/drivers/playmark.cpp
index 114a667..55c5040 100644
--- a/src/mame/drivers/playmark.cpp
+++ b/src/mame/drivers/playmark.cpp
@@ -207,17 +207,11 @@ READ8_MEMBER(playmark_state::playmark_snd_flag_r)
 
 WRITE8_MEMBER(playmark_state::playmark_oki_banking_w)
 {
-	logerror("PC$%03x Writing %02x to PortA  (OKI bank select) previous bank was %02x\n",space.device().safe_pcbase(),data,m_old_oki_bank);
+	logerror("PC$%03x Writing %02x to PortA  (OKI bank select)\n",space.device().safe_pcbase(),data);
 
-	if (m_old_oki_bank != (data & 7))
-	{
-		m_old_oki_bank = data & 7;
+	int bank = data & 7;
 
-		if (((m_old_oki_bank - 1) * 0x40000) < memregion("oki")->bytes())
-		{
-			m_oki->set_rom_bank(m_old_oki_bank - 1);
-		}
-	}
+	m_okibank->set_entry(bank & (m_oki_numbanks - 1));
 }
 
 WRITE8_MEMBER(playmark_state::playmark_oki_w)
@@ -252,17 +246,8 @@ WRITE8_MEMBER(playmark_state::hrdtimes_snd_control_w)
 {
 	/*  This port controls communications to and from the 68K and the OKI device. See playmark_snd_control_w above. OKI banking is also handled here. */
 
-	if (m_old_oki_bank != (data & 3))
-	{
-//      logerror("PC$%03x Writing %02x to PortC (OKI bank select bits). Previous bank was %02x\n",space.device().safe_pcbase(),(data&3),m_old_oki_bank);
-
-		m_old_oki_bank = data & 3;
-
-		if ((m_old_oki_bank * 0x40000) < memregion("oki")->bytes())
-		{
-			m_oki->set_rom_bank(m_old_oki_bank);
-		}
-	}
+	int bank = data & 3;
+	m_okibank->set_entry(bank & (m_oki_numbanks - 1));
 
 	m_oki_control = data;
 
@@ -340,7 +325,7 @@ static ADDRESS_MAP_START( wbeachvl_main_map, AS_PROGRAM, 16, playmark_state )
 	AM_RANGE(0x710018, 0x710019) AM_READ_PORT("P3")
 	AM_RANGE(0x71001a, 0x71001b) AM_READ_PORT("P4")
 //  AM_RANGE(0x71001c, 0x71001d) AM_READ(playmark_snd_status???)
-//  AM_RANGE(0x71001e, 0x71001f) AM_WRITE(playmark_snd_command_w)
+	AM_RANGE(0x71001e, 0x71001f) AM_WRITE(playmark_snd_command_w)
 	AM_RANGE(0x780000, 0x780fff) AM_DEVWRITE("palette", palette_device, write) AM_SHARE("palette")
 	AM_RANGE(0xff0000, 0xffffff) AM_RAM
 ADDRESS_MAP_END
@@ -426,6 +411,12 @@ static ADDRESS_MAP_START( luckboomh_main_map, AS_PROGRAM, 16, playmark_state )
 	AM_RANGE(0xff8000, 0xffffff) AM_RAM
 ADDRESS_MAP_END
 
+static ADDRESS_MAP_START( oki_map, AS_0, 8, playmark_state )
+	AM_RANGE(0x00000, 0x1ffff) AM_ROM
+	AM_RANGE(0x20000, 0x3ffff) AM_ROMBANK("okibank")
+ADDRESS_MAP_END
+
+
 
 static INPUT_PORTS_START( bigtwin )
 	PORT_START("SYSTEM")
@@ -1169,6 +1160,20 @@ static GFXDECODE_START( bigtwinb )
 	GFXDECODE_ENTRY( "gfx1", 0x40000, hotmind_charlayout,  0x200, 16 )    /* colors 0x200-0x2ff */
 GFXDECODE_END
 
+void playmark_state::configure_oki_banks()
+{
+	if (m_okibank)
+	{
+		const uint32_t len    =   memregion("oki")->bytes();
+		uint8_t *rgn          =   memregion("oki")->base();
+
+		m_oki_numbanks = len / 0x20000;
+
+		m_okibank->configure_entries(0, m_oki_numbanks, rgn, 0x20000);
+		m_okibank->set_entry(1);
+	}
+}
+
 MACHINE_START_MEMBER(playmark_state,playmark)
 {
 	save_item(NAME(m_bgscrollx));
@@ -1183,10 +1188,13 @@ MACHINE_START_MEMBER(playmark_state,playmark)
 	save_item(NAME(m_snd_flag));
 	save_item(NAME(m_oki_control));
 	save_item(NAME(m_oki_command));
-	save_item(NAME(m_old_oki_bank));
 	save_item(NAME(m_dispenser_latch));
+
+	configure_oki_banks();
 }
 
+
+
 MACHINE_RESET_MEMBER(playmark_state,playmark)
 {
 	m_bgscrollx = 0;
@@ -1201,7 +1209,6 @@ MACHINE_RESET_MEMBER(playmark_state,playmark)
 	m_snd_flag = 0;
 	m_oki_control = 0;
 	m_oki_command = 0;
-	m_old_oki_bank = 0;
 	m_dispenser_latch = 0;
 }
 
@@ -1243,6 +1250,7 @@ static MACHINE_CONFIG_START( bigtwin, playmark_state )
 
 	MCFG_OKIM6295_ADD("oki", 1000000, OKIM6295_PIN7_HIGH)
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
+	MCFG_DEVICE_ADDRESS_MAP(AS_0, oki_map)
 MACHINE_CONFIG_END
 
 static MACHINE_CONFIG_START( bigtwinb, playmark_state )
@@ -1283,6 +1291,7 @@ static MACHINE_CONFIG_START( bigtwinb, playmark_state )
 
 	MCFG_OKIM6295_ADD("oki", 1000000, OKIM6295_PIN7_HIGH)
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
+	MCFG_DEVICE_ADDRESS_MAP(AS_0, oki_map)
 MACHINE_CONFIG_END
 
 static MACHINE_CONFIG_START( wbeachvl, playmark_state )
@@ -1293,13 +1302,13 @@ static MACHINE_CONFIG_START( wbeachvl, playmark_state )
 	MCFG_CPU_VBLANK_INT_DRIVER("screen", playmark_state,  irq2_line_hold)
 
 	MCFG_CPU_ADD("audiocpu", PIC16C57, XTAL_24MHz/2)    /* 12MHz with internal 4x divisor */
-	MCFG_PIC16C5x_WRITE_A_CB(WRITE8(playmark_state, playmark_oki_banking_w))
+	MCFG_PIC16C5x_WRITE_A_CB(WRITE8(playmark_state, playmark_oki_banking_w)) // wrong?
 	MCFG_PIC16C5x_READ_B_CB(READ8(playmark_state, playmark_snd_command_r))
 	MCFG_PIC16C5x_WRITE_B_CB(WRITE8(playmark_state, playmark_oki_w))
 	MCFG_PIC16C5x_READ_C_CB(READ8(playmark_state, playmark_snd_flag_r))
 	MCFG_PIC16C5x_WRITE_C_CB(WRITE8(playmark_state, playmark_snd_control_w))
+//  MCFG_PIC16C5x_WRITE_C_CB(WRITE8(playmark_state, hrdtimes_snd_control_w)) // probably closer to this, but this only supports 2 sample bank bits
 	MCFG_PIC16C5x_T0_CB(READLINE(playmark_state, PIC16C5X_T0_clk_r))
-	MCFG_DEVICE_DISABLE()       /* Internal code is not dumped yet */
 
 	MCFG_EEPROM_SERIAL_93C46_ADD("eeprom")
 	MCFG_EEPROM_SERIAL_DEFAULT_VALUE(0)
@@ -1327,6 +1336,7 @@ static MACHINE_CONFIG_START( wbeachvl, playmark_state )
 
 	MCFG_OKIM6295_ADD("oki", 1000000, OKIM6295_PIN7_HIGH)
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
+	MCFG_DEVICE_ADDRESS_MAP(AS_0, oki_map)
 MACHINE_CONFIG_END
 
 static MACHINE_CONFIG_START( excelsr, playmark_state )
@@ -1367,6 +1377,7 @@ static MACHINE_CONFIG_START( excelsr, playmark_state )
 
 	MCFG_OKIM6295_ADD("oki", XTAL_1MHz, OKIM6295_PIN7_HIGH) /* 1MHz resonator */
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
+	MCFG_DEVICE_ADDRESS_MAP(AS_0, oki_map)
 MACHINE_CONFIG_END
 
 static MACHINE_CONFIG_START( hrdtimes, playmark_state )
@@ -1408,6 +1419,7 @@ static MACHINE_CONFIG_START( hrdtimes, playmark_state )
 
 	MCFG_OKIM6295_ADD("oki", XTAL_1MHz, OKIM6295_PIN7_HIGH) /* verified on pcb */
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
+	MCFG_DEVICE_ADDRESS_MAP(AS_0, oki_map)
 MACHINE_CONFIG_END
 
 static MACHINE_CONFIG_START( hotmind, playmark_state )
@@ -1454,6 +1466,7 @@ static MACHINE_CONFIG_START( hotmind, playmark_state )
 
 	MCFG_OKIM6295_ADD("oki", XTAL_1MHz, OKIM6295_PIN7_HIGH)  /* verified on pcb */
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
+	MCFG_DEVICE_ADDRESS_MAP(AS_0, oki_map)
 MACHINE_CONFIG_END
 
 static MACHINE_CONFIG_START( luckboomh, playmark_state )
@@ -1499,6 +1512,7 @@ static MACHINE_CONFIG_START( luckboomh, playmark_state )
 
 	MCFG_OKIM6295_ADD("oki", XTAL_1MHz, OKIM6295_PIN7_HIGH)  /* verified on pcb */
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
+	MCFG_DEVICE_ADDRESS_MAP(AS_0, oki_map)
 MACHINE_CONFIG_END
 
 
@@ -1573,8 +1587,9 @@ ROM_START( wbeachvl )
 	ROM_LOAD16_BYTE( "wbv_02.bin",   0x000000, 0x40000, CRC(c7cca29e) SHA1(03af361081d688c4204a95f7f5babcc598b72c23) )
 	ROM_LOAD16_BYTE( "wbv_03.bin",   0x000001, 0x40000, CRC(db4e69d5) SHA1(119bf35a463d279ddde67ab08f6f1bab9f05cf0c) )
 
-	ROM_REGION( 0x1000, "audiocpu", ROMREGION_ERASE00 ) /* sound (PIC16C57) */
-	ROM_LOAD( "pic16c57",     0x0000, 0x1000, NO_DUMP )
+	ROM_REGION( 0x1009, "audiocpu", ROMREGION_ERASE00 ) /* sound (PIC16C57) */
+	// 0x1000 rom data (actually 0x800 12-bit words), + 0x9 config bytes
+	ROM_LOAD( "pic16c57",       0x00000, 0x1009, CRC(35439064) SHA1(ab0c5bafd76a2cb2a2e5ddb9d0578fd7e2241e43) )
 
 	ROM_REGION( 0x600000, "gfx1", 0 )
 	ROM_LOAD( "wbv_10.bin",   0x000000, 0x80000, CRC(50680f0b) SHA1(ed76ef6ced70ba7e9558162aa94bbe9f19bbabe6) )
@@ -1591,26 +1606,10 @@ ROM_START( wbeachvl )
 	ROM_LOAD( "wbv_09.bin",   0x580000, 0x20000, CRC(894ce354) SHA1(331aeabbe10cd645776da2dc0829acc2275e72dc) )
 	/* 5a0000-5fffff is empty */
 
-	ROM_REGION( 0x100000, "user2", 0 )  /* OKIM6295 samples */
-	ROM_LOAD( "wbv_01.bin",   0x00000, 0x100000, CRC(ac33f25f) SHA1(5d9ed16650aeb297d565376a99b31c88ab611668) )
-
 	/* $00000-$20000 stays the same in all sound banks, */
 	/* the second half of the bank is what gets switched */
-	ROM_REGION( 0x1c0000, "oki", 0 ) /* Samples */
-	ROM_COPY( "user2", 0x000000, 0x000000, 0x020000)
-	ROM_COPY( "user2", 0x020000, 0x020000, 0x020000)
-	ROM_COPY( "user2", 0x000000, 0x040000, 0x020000)
-	ROM_COPY( "user2", 0x040000, 0x060000, 0x020000)
-	ROM_COPY( "user2", 0x000000, 0x080000, 0x020000)
-	ROM_COPY( "user2", 0x060000, 0x0a0000, 0x020000)
-	ROM_COPY( "user2", 0x000000, 0x0c0000, 0x020000)
-	ROM_COPY( "user2", 0x080000, 0x0e0000, 0x020000)
-	ROM_COPY( "user2", 0x000000, 0x100000, 0x020000)
-	ROM_COPY( "user2", 0x0a0000, 0x120000, 0x020000)
-	ROM_COPY( "user2", 0x000000, 0x140000, 0x020000)
-	ROM_COPY( "user2", 0x0c0000, 0x160000, 0x020000)
-	ROM_COPY( "user2", 0x000000, 0x180000, 0x020000)
-	ROM_COPY( "user2", 0x0e0000, 0x1a0000, 0x020000)
+	ROM_REGION( 0x100000, "oki", 0 ) /* Samples */
+	ROM_LOAD( "wbv_01.bin",   0x00000, 0x100000, CRC(ac33f25f) SHA1(5d9ed16650aeb297d565376a99b31c88ab611668) )
 ROM_END
 
 ROM_START( wbeachvl2 )
@@ -1618,8 +1617,9 @@ ROM_START( wbeachvl2 )
 	ROM_LOAD16_BYTE( "2.bin",   0x000000, 0x40000, CRC(8993487e) SHA1(c927ae655807f9046f66ff96a30bd2c6fa671566) )
 	ROM_LOAD16_BYTE( "3.bin",   0x000001, 0x40000, CRC(15904789) SHA1(640c80bbf7302529e1a39c2ae60e018ecb176478) )
 
-	ROM_REGION( 0x1000, "audiocpu", ROMREGION_ERASE00 ) /* sound (PIC16C57) */
-	ROM_LOAD( "pic16c57",     0x0000, 0x1000, NO_DUMP )
+	ROM_REGION( 0x1009, "audiocpu", ROMREGION_ERASE00 ) /* sound (PIC16C57) */
+	// 0x1000 rom data (actually 0x800 12-bit words), + 0x9 config bytes
+	ROM_LOAD( "pic16c57",       0x00000, 0x1009, CRC(35439064) SHA1(ab0c5bafd76a2cb2a2e5ddb9d0578fd7e2241e43) )
 
 	ROM_REGION( 0x600000, "gfx1", 0 )
 	ROM_LOAD( "wbv_10.bin",   0x000000, 0x80000, CRC(50680f0b) SHA1(ed76ef6ced70ba7e9558162aa94bbe9f19bbabe6) )
@@ -1636,26 +1636,10 @@ ROM_START( wbeachvl2 )
 	ROM_LOAD( "wbv_09.bin",   0x580000, 0x20000, CRC(894ce354) SHA1(331aeabbe10cd645776da2dc0829acc2275e72dc) )
 	/* 5a0000-5fffff is empty */
 
-	ROM_REGION( 0x100000, "user2", 0 )  /* OKIM6295 samples */
-	ROM_LOAD( "wbv_01.bin",   0x00000, 0x100000, CRC(ac33f25f) SHA1(5d9ed16650aeb297d565376a99b31c88ab611668) )
-
 	/* $00000-$20000 stays the same in all sound banks, */
 	/* the second half of the bank is what gets switched */
-	ROM_REGION( 0x1c0000, "oki", 0 ) /* Samples */
-	ROM_COPY( "user2", 0x000000, 0x000000, 0x020000)
-	ROM_COPY( "user2", 0x020000, 0x020000, 0x020000)
-	ROM_COPY( "user2", 0x000000, 0x040000, 0x020000)
-	ROM_COPY( "user2", 0x040000, 0x060000, 0x020000)
-	ROM_COPY( "user2", 0x000000, 0x080000, 0x020000)
-	ROM_COPY( "user2", 0x060000, 0x0a0000, 0x020000)
-	ROM_COPY( "user2", 0x000000, 0x0c0000, 0x020000)
-	ROM_COPY( "user2", 0x080000, 0x0e0000, 0x020000)
-	ROM_COPY( "user2", 0x000000, 0x100000, 0x020000)
-	ROM_COPY( "user2", 0x0a0000, 0x120000, 0x020000)
-	ROM_COPY( "user2", 0x000000, 0x140000, 0x020000)
-	ROM_COPY( "user2", 0x0c0000, 0x160000, 0x020000)
-	ROM_COPY( "user2", 0x000000, 0x180000, 0x020000)
-	ROM_COPY( "user2", 0x0e0000, 0x1a0000, 0x020000)
+	ROM_REGION( 0x100000, "oki", 0 ) /* Samples */
+	ROM_LOAD( "wbv_01.bin",   0x00000, 0x100000, CRC(ac33f25f) SHA1(5d9ed16650aeb297d565376a99b31c88ab611668) )
 ROM_END
 
 ROM_START( wbeachvl3 )
@@ -1663,8 +1647,9 @@ ROM_START( wbeachvl3 )
 	ROM_LOAD16_BYTE( "2.u16",   0x000000, 0x40000, CRC(f0f4c282) SHA1(94850b45368c3d09629852adc8ca08164b7a7a94) )
 	ROM_LOAD16_BYTE( "3.u15",   0x000001, 0x40000, CRC(99775c21) SHA1(fa80a81c59142abcf751352d7a7f9e0d3b5172c9) )
 
-	ROM_REGION( 0x1000, "audiocpu", ROMREGION_ERASE00 ) /* sound (PIC16C57) */
-	ROM_LOAD( "pic16c57",     0x0000, 0x1000, NO_DUMP )
+	ROM_REGION( 0x1009, "audiocpu", ROMREGION_ERASE00 ) /* sound (PIC16C57) */
+	// 0x1000 rom data (actually 0x800 12-bit words), + 0x9 config bytes
+	ROM_LOAD( "pic16c57",       0x00000, 0x1009, CRC(35439064) SHA1(ab0c5bafd76a2cb2a2e5ddb9d0578fd7e2241e43) )
 
 	ROM_REGION( 0x600000, "gfx1", 0 )
 	ROM_LOAD( "wbv_10.bin",   0x000000, 0x80000, CRC(50680f0b) SHA1(ed76ef6ced70ba7e9558162aa94bbe9f19bbabe6) )
@@ -1681,26 +1666,10 @@ ROM_START( wbeachvl3 )
 	ROM_LOAD( "wbv_09.bin",   0x580000, 0x20000, CRC(894ce354) SHA1(331aeabbe10cd645776da2dc0829acc2275e72dc) )
 	/* 5a0000-5fffff is empty */
 
-	ROM_REGION( 0x100000, "user2", 0 )  /* OKIM6295 samples */
-	ROM_LOAD( "wbv_01.bin",   0x00000, 0x100000, CRC(ac33f25f) SHA1(5d9ed16650aeb297d565376a99b31c88ab611668) )
-
 	/* $00000-$20000 stays the same in all sound banks, */
 	/* the second half of the bank is what gets switched */
-	ROM_REGION( 0x1c0000, "oki", 0 ) /* Samples */
-	ROM_COPY( "user2", 0x000000, 0x000000, 0x020000)
-	ROM_COPY( "user2", 0x020000, 0x020000, 0x020000)
-	ROM_COPY( "user2", 0x000000, 0x040000, 0x020000)
-	ROM_COPY( "user2", 0x040000, 0x060000, 0x020000)
-	ROM_COPY( "user2", 0x000000, 0x080000, 0x020000)
-	ROM_COPY( "user2", 0x060000, 0x0a0000, 0x020000)
-	ROM_COPY( "user2", 0x000000, 0x0c0000, 0x020000)
-	ROM_COPY( "user2", 0x080000, 0x0e0000, 0x020000)
-	ROM_COPY( "user2", 0x000000, 0x100000, 0x020000)
-	ROM_COPY( "user2", 0x0a0000, 0x120000, 0x020000)
-	ROM_COPY( "user2", 0x000000, 0x140000, 0x020000)
-	ROM_COPY( "user2", 0x0c0000, 0x160000, 0x020000)
-	ROM_COPY( "user2", 0x000000, 0x180000, 0x020000)
-	ROM_COPY( "user2", 0x0e0000, 0x1a0000, 0x020000)
+	ROM_REGION( 0x100000, "oki", 0 ) /* Samples */
+	ROM_LOAD( "wbv_01.bin",   0x00000, 0x100000, CRC(ac33f25f) SHA1(5d9ed16650aeb297d565376a99b31c88ab611668) )
 ROM_END
 
 ROM_START( excelsr )
@@ -1730,18 +1699,10 @@ ROM_START( excelsr )
 	ROM_LOAD( "23.u323",      0x100000, 0x80000, CRC(d8e1453b) SHA1(a3edb05abe486d4cce30f5caf14be619b6886f7c) )
 	ROM_LOAD( "27.u324",      0x180000, 0x80000, CRC(eca2c079) SHA1(a07957b427d55c8ca1efb0e83ee3b603f06bed58) )
 
-	ROM_REGION( 0x80000, "user2", 0 )   /* OKIM6295 samples */
-	ROM_LOAD( "16.i013",      0x000000, 0x80000, CRC(7ed9da5d) SHA1(352f1e89613feb1902b6d87adb996ed1c1d8108e) )
-
 	/* $00000-$20000 stays the same in all sound banks, */
 	/* the second half of the bank is what gets switched */
-	ROM_REGION( 0xc0000, "oki", 0 ) /* Samples */
-	ROM_COPY( "user2", 0x000000, 0x000000, 0x020000)
-	ROM_COPY( "user2", 0x020000, 0x020000, 0x020000)
-	ROM_COPY( "user2", 0x000000, 0x040000, 0x020000)
-	ROM_COPY( "user2", 0x040000, 0x060000, 0x020000)
-	ROM_COPY( "user2", 0x000000, 0x080000, 0x020000)
-	ROM_COPY( "user2", 0x060000, 0x0a0000, 0x020000)
+	ROM_REGION( 0x80000, "oki", 0 ) /* Samples */
+	ROM_LOAD( "16.i013",      0x000000, 0x80000, CRC(7ed9da5d) SHA1(352f1e89613feb1902b6d87adb996ed1c1d8108e) )
 ROM_END
 
 ROM_START( excelsra )
@@ -1771,18 +1732,10 @@ ROM_START( excelsra )
 	ROM_LOAD( "23.u323",      0x100000, 0x80000, CRC(d8e1453b) SHA1(a3edb05abe486d4cce30f5caf14be619b6886f7c) )
 	ROM_LOAD( "27.u324",      0x180000, 0x80000, CRC(eca2c079) SHA1(a07957b427d55c8ca1efb0e83ee3b603f06bed58) )
 
-	ROM_REGION( 0x80000, "user2", 0 )   /* OKIM6295 samples */
-	ROM_LOAD( "16.i013",      0x000000, 0x80000, CRC(7ed9da5d) SHA1(352f1e89613feb1902b6d87adb996ed1c1d8108e) )
-
 	/* $00000-$20000 stays the same in all sound banks, */
 	/* the second half of the bank is what gets switched */
-	ROM_REGION( 0xc0000, "oki", 0 ) /* Samples */
-	ROM_COPY( "user2", 0x000000, 0x000000, 0x020000)
-	ROM_COPY( "user2", 0x020000, 0x020000, 0x020000)
-	ROM_COPY( "user2", 0x000000, 0x040000, 0x020000)
-	ROM_COPY( "user2", 0x040000, 0x060000, 0x020000)
-	ROM_COPY( "user2", 0x000000, 0x080000, 0x020000)
-	ROM_COPY( "user2", 0x060000, 0x0a0000, 0x020000)
+	ROM_REGION( 0x80000, "oki", 0 ) /* Samples */
+	ROM_LOAD( "16.i013",      0x000000, 0x80000, CRC(7ed9da5d) SHA1(352f1e89613feb1902b6d87adb996ed1c1d8108e) )
 ROM_END
 
 ROM_START( hrdtimes )
@@ -1810,15 +1763,8 @@ ROM_START( hrdtimes )
 
 	/* $00000-$20000 stays the same in all sound banks, */
 	/* the second half of the bank is what gets switched */
-	ROM_REGION( 0x100000, "oki", 0 ) /* Samples */
-	ROM_LOAD( "30.io13",      0x00000, 0x20000, CRC(fa5e50ae) SHA1(f3bd87c83fca9269cc2f19db1fbf55540c96f931) )
-	ROM_CONTINUE(             0x60000, 0x20000 )
-	ROM_CONTINUE(             0xa0000, 0x20000 )
-	ROM_CONTINUE(             0xe0000, 0x20000 )
-	ROM_COPY( "oki", 0x000000, 0x20000, 0x20000 )
-	ROM_COPY( "oki", 0x000000, 0x40000, 0x20000 )
-	ROM_COPY( "oki", 0x000000, 0x80000, 0x20000 )
-	ROM_COPY( "oki", 0x000000, 0xc0000, 0x20000 )
+	ROM_REGION( 0x80000, "oki", 0 ) /* Samples */
+	ROM_LOAD( "30.io13",      0x00000, 0x80000, CRC(fa5e50ae) SHA1(f3bd87c83fca9269cc2f19db1fbf55540c96f931) )
 ROM_END
 
 /* Different revision of the PCB, uses larger gfx ROMs, however the content is the same */
@@ -1844,15 +1790,8 @@ ROM_START( hrdtimesa )
 
 	/* $00000-$20000 stays the same in all sound banks, */
 	/* the second half of the bank is what gets switched */
-	ROM_REGION( 0x100000, "oki", 0 ) /* Samples */
-	ROM_LOAD( "io13.bin",     0x00000, 0x20000, CRC(fa5e50ae) SHA1(f3bd87c83fca9269cc2f19db1fbf55540c96f931) )
-	ROM_CONTINUE(             0x60000, 0x20000 )
-	ROM_CONTINUE(             0xa0000, 0x20000 )
-	ROM_CONTINUE(             0xe0000, 0x20000 )
-	ROM_COPY( "oki", 0x000000, 0x20000, 0x20000 )
-	ROM_COPY( "oki", 0x000000, 0x40000, 0x20000 )
-	ROM_COPY( "oki", 0x000000, 0x80000, 0x20000 )
-	ROM_COPY( "oki", 0x000000, 0xc0000, 0x20000 )
+	ROM_REGION( 0x80000, "oki", 0 ) /* Samples */
+	ROM_LOAD( "io13.bin",     0x00000, 0x80000, CRC(fa5e50ae) SHA1(f3bd87c83fca9269cc2f19db1fbf55540c96f931) )
 ROM_END
 
 /*
@@ -1926,11 +1865,8 @@ ROM_START( hotmind )
 	ROM_LOAD16_BYTE( "25.u84",       0x40000, 0x20000, CRC(c4fd4445) SHA1(ab0c5a328a312740595b5c92a1050527140518f3) )
 	ROM_LOAD16_BYTE( "29.u83",       0x40001, 0x20000, CRC(0bebfb53) SHA1(d4342f808141b70af98c370004153a31d120e2a4) )
 
-	ROM_REGION( 0x80000, "oki", 0 ) /* Samples */
-	ROM_LOAD( "20.io13",      0x00000, 0x20000, CRC(0bf3a3e5) SHA1(2ae06f37a6bcd20bc5fbaa90d970aba2ebf3cf5a) )
-	ROM_CONTINUE(             0x60000, 0x20000 )
-	ROM_COPY( "oki", 0x000000, 0x20000, 0x20000 )
-	ROM_COPY( "oki", 0x000000, 0x40000, 0x20000 )
+	ROM_REGION( 0x40000, "oki", 0 ) /* Samples */
+	ROM_LOAD( "20.io13",      0x00000, 0x40000, CRC(0bf3a3e5) SHA1(2ae06f37a6bcd20bc5fbaa90d970aba2ebf3cf5a) )
 
 	ROM_REGION( 0x8000, "plds", 0 )     /* These were read protected */
 	ROM_LOAD( "palce16v8h-25-pc4_u58.jed",   0x0000, 0xb89,  BAD_DUMP CRC(ba88c1da) SHA1(9b55e96eee44a467bdfbf760137ccb2fb3afedf0) )
@@ -1969,14 +1905,12 @@ ROM_START( luckboomh )
 	ROM_LOAD16_BYTE( "25.u84",       0x40000, 0x20000, CRC(e1ab5cf5) SHA1(f76d00537cfd6f09439e44071875bf021622fd07) )
 	ROM_LOAD16_BYTE( "29.u83",       0x40001, 0x20000, CRC(9572d2d4) SHA1(90d55b1f13dc93041160530e8c1ce8def6e02bcf) )
 
-	ROM_REGION( 0x80000, "oki", 0 ) /* Samples */
-	ROM_LOAD( "20.io13",      0x00000, 0x20000, CRC(0d42c0a3) SHA1(1b1d4c7dcbb063e8bf133063770b753947d1a017) )
-	ROM_CONTINUE(             0x60000, 0x20000 )
-	ROM_COPY( "oki", 0x000000, 0x20000, 0x20000 )
-	ROM_COPY( "oki", 0x000000, 0x40000, 0x20000 )
+	ROM_REGION( 0x40000, "oki", 0 ) /* Samples */
+	ROM_LOAD( "20.io13",      0x00000, 0x40000, CRC(0d42c0a3) SHA1(1b1d4c7dcbb063e8bf133063770b753947d1a017) )
 ROM_END
 
 
+
 uint8_t playmark_state::playmark_asciitohex(uint8_t data)
 {
 	/* Convert ASCII data to HEX */
@@ -2061,9 +1995,9 @@ DRIVER_INIT_MEMBER(playmark_state,pic_decode)
 
 GAME( 1995, bigtwin,   0,        bigtwin,   bigtwin,   playmark_state, pic_decode, ROT0, "Playmark", "Big Twin", MACHINE_SUPPORTS_SAVE )
 GAME( 1995, bigtwinb,  bigtwin,  bigtwinb,  bigtwinb,  playmark_state, pic_decode, ROT0, "Playmark", "Big Twin (No Girls Conversion)", MACHINE_SUPPORTS_SAVE )
-GAME( 1995, wbeachvl,  0,        wbeachvl,  wbeachvl,  driver_device,  0,          ROT0, "Playmark", "World Beach Volley (set 1)", MACHINE_NO_SOUND | MACHINE_SUPPORTS_SAVE )
-GAME( 1995, wbeachvl2, wbeachvl, wbeachvl,  wbeachvl,  driver_device,  0,          ROT0, "Playmark", "World Beach Volley (set 2)", MACHINE_NO_SOUND | MACHINE_SUPPORTS_SAVE )
-GAME( 1995, wbeachvl3, wbeachvl, wbeachvl,  wbeachvl,  driver_device,  0,          ROT0, "Playmark", "World Beach Volley (set 3)", MACHINE_NO_SOUND | MACHINE_SUPPORTS_SAVE )
+GAME( 1995, wbeachvl,  0,        wbeachvl,  wbeachvl,  driver_device,  0,          ROT0, "Playmark", "World Beach Volley (set 1)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
+GAME( 1995, wbeachvl2, wbeachvl, wbeachvl,  wbeachvl,  driver_device,  0,          ROT0, "Playmark", "World Beach Volley (set 2)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
+GAME( 1995, wbeachvl3, wbeachvl, wbeachvl,  wbeachvl,  driver_device,  0,          ROT0, "Playmark", "World Beach Volley (set 3)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
 GAME( 1996, excelsr,   0,        excelsr,   excelsr,   playmark_state, pic_decode, ROT0, "Playmark", "Excelsior (set 1)", MACHINE_SUPPORTS_SAVE )
 GAME( 1996, excelsra,  excelsr,  excelsr,   excelsr,   playmark_state, pic_decode, ROT0, "Playmark", "Excelsior (set 2)", MACHINE_SUPPORTS_SAVE )
 GAME( 1994, hrdtimes,  0,        hrdtimes,  hrdtimes,  driver_device,  0,          ROT0, "Playmark", "Hard Times (set 1)", MACHINE_NO_SOUND | MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/drivers/poly.cpp b/src/mame/drivers/poly.cpp
index 9561fa4..3557dd0 100644
--- a/src/mame/drivers/poly.cpp
+++ b/src/mame/drivers/poly.cpp
@@ -183,8 +183,7 @@ static MACHINE_CONFIG_START( poly, poly_state )
 	MCFG_PIA_IRQA_HANDLER(INPUTLINE("maincpu", M6809_IRQ_LINE))
 	MCFG_PIA_IRQB_HANDLER(INPUTLINE("maincpu", M6809_IRQ_LINE))
 
-	MCFG_DEVICE_ADD("ptm", PTM6840, 0)
-	MCFG_PTM6840_INTERNAL_CLOCK(XTAL_12MHz / 3)
+	MCFG_DEVICE_ADD("ptm", PTM6840, XTAL_12MHz / 3)
 	MCFG_PTM6840_EXTERNAL_CLOCKS(0, 0, 0)
 	MCFG_PTM6840_OUT1_CB(WRITELINE(poly_state, ptm_o2_callback))
 	MCFG_PTM6840_OUT2_CB(WRITELINE(poly_state, ptm_o3_callback))
diff --git a/src/mame/drivers/powerbal.cpp b/src/mame/drivers/powerbal.cpp
index 675a0a8..879b0c0 100644
--- a/src/mame/drivers/powerbal.cpp
+++ b/src/mame/drivers/powerbal.cpp
@@ -78,13 +78,8 @@ WRITE16_MEMBER(powerbal_state::tile_banking_w)
 
 WRITE16_MEMBER(powerbal_state::oki_banking)
 {
-	if (data & 3)
-	{
-		int addr = (data & 3) - 1;
-
-		if (addr * 0x40000 < memregion("oki")->bytes())
-			m_oki->set_rom_bank(addr);
-	}
+	int bank = data & 3;
+	m_okibank->set_entry(bank & (m_oki_numbanks - 1));
 }
 
 static ADDRESS_MAP_START( magicstk_main_map, AS_PROGRAM, 16, powerbal_state )
@@ -128,6 +123,10 @@ static ADDRESS_MAP_START( powerbal_main_map, AS_PROGRAM, 16, powerbal_state )
 	AM_RANGE(0x103000, 0x103fff) AM_RAM
 ADDRESS_MAP_END
 
+static ADDRESS_MAP_START( oki_map, AS_0, 8, powerbal_state )
+	AM_RANGE(0x00000, 0x1ffff) AM_ROM
+	AM_RANGE(0x20000, 0x3ffff) AM_ROMBANK("okibank")
+ADDRESS_MAP_END
 
 static INPUT_PORTS_START( powerbal )
 	PORT_START("IN0")
@@ -484,6 +483,7 @@ MACHINE_START_MEMBER(powerbal_state,powerbal)
 MACHINE_RESET_MEMBER(powerbal_state,powerbal)
 {
 	m_tilebank = 0;
+	configure_oki_banks();
 }
 
 static MACHINE_CONFIG_START( powerbal, powerbal_state )
@@ -516,6 +516,7 @@ static MACHINE_CONFIG_START( powerbal, powerbal_state )
 
 	MCFG_OKIM6295_ADD("oki", 1000000, OKIM6295_PIN7_HIGH)
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
+	MCFG_DEVICE_ADDRESS_MAP(AS_0, oki_map)
 MACHINE_CONFIG_END
 
 static MACHINE_CONFIG_START( magicstk, powerbal_state )
@@ -551,6 +552,7 @@ static MACHINE_CONFIG_START( magicstk, powerbal_state )
 
 	MCFG_OKIM6295_ADD("oki", 1000000, OKIM6295_PIN7_HIGH)
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
+	MCFG_DEVICE_ADDRESS_MAP(AS_0, oki_map)
 MACHINE_CONFIG_END
 
 
@@ -622,12 +624,8 @@ ROM_START( powerbal )
 
 	/* $00000-$20000 stays the same in all sound banks, */
 	/* the second half of the bank is the area that gets switched */
-	ROM_REGION( 0xc0000, "oki", 0 ) /* OKI Samples */
-	ROM_LOAD( "1.u16",        0x00000, 0x40000, CRC(12776dbc) SHA1(9ab9930fd581296642834d2cb4ba65264a588af3) )
-	ROM_CONTINUE(             0x60000, 0x20000 )
-	ROM_CONTINUE(             0xa0000, 0x20000 )
-	ROM_COPY( "oki",  0x000000, 0x40000, 0x20000)
-	ROM_COPY( "oki",  0x000000, 0x80000, 0x20000)
+	ROM_REGION( 0x80000, "oki", 0 ) /* OKI Samples */
+	ROM_LOAD( "1.u16",        0x00000, 0x80000, CRC(12776dbc) SHA1(9ab9930fd581296642834d2cb4ba65264a588af3) )
 
 	ROM_REGION( 0x1200, "plds", 0 )
 	ROM_LOAD( "palce16v8h.u102",  0x0000, 0x0117, NO_DUMP ) /* PAL is read protected */
diff --git a/src/mame/drivers/prodigy.cpp b/src/mame/drivers/prodigy.cpp
index 0ce8f2f..8ffc003 100644
--- a/src/mame/drivers/prodigy.cpp
+++ b/src/mame/drivers/prodigy.cpp
@@ -6,6 +6,31 @@
 
     TODO: Everything
 
+    +-------------------------------------------------------------------------------------+
+    |LEDS--------------------------------------------+        +-----------------+         |
+    | | |              o o o o o o o o COLCN         |        |                 |         |
+    | V |                                            |        | 4 char BCD LED  |         |
+    | O | 8                                          |        +-----------------+         |
+    |   |                                      ROWCN |        |||||||||||||||||||  ____   |
+    | O | 7                                         o|+----------------------+    /    \  |
+    |   |                                           o||  VIA                 |   ( beep ) |
+    | O | 6                                         o|| R6522                |    \____/  |
+    |   |                                           o|+----------------------+            |
+    | O | 5                                         o|+----------------------+            |
+    |   |                                           o||  CPU                 |            |
+    | O | 4         8 x 8 button matrix             o|| R6502-13             |   +--+  __ |
+    |   |                                           o|+----------------------+   |74| PWR||
+    | O | 3                                         o|   o    o  +-------------+ |LS| SW >|
+    |   |                                            | +=======+ |  ROM        | |14|  __||
+    | O | 2                                          | | 2MHz  | | R2912       | +--+     |
+    |   |                                            | |  XTAL | +-------------+     +--+ |
+    | O | 1                                          |++-------+ +-------------+     |74| |
+    |   |                                            || 74145N | |  RAM        |     |LS| |
+    |   |   A     B    C    D    E    F     G    H   |+--------+ | M58725P     |     |00| |
+    |   +--------------------------------------------+           +-------------+     +--+ |
+    |LEDS-> O     O    O    O    O    O     O    O                 OOOOOOOOOOO KPDCN      |
+    +-------------------------------------------------------------------------------------+
+
 ******************************************************************************/
 
 #include "emu.h"
diff --git a/src/mame/drivers/pturn.cpp b/src/mame/drivers/pturn.cpp
index 09978a2..d519858 100644
--- a/src/mame/drivers/pturn.cpp
+++ b/src/mame/drivers/pturn.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina,Tatsuyuki Satoh
 /*
 Parallel Turn
diff --git a/src/mame/drivers/pulsar.cpp b/src/mame/drivers/pulsar.cpp
index 9a01250..88af384 100644
--- a/src/mame/drivers/pulsar.cpp
+++ b/src/mame/drivers/pulsar.cpp
@@ -55,6 +55,7 @@ public:
 		m_brg(*this, "brg"),
 		m_fdc (*this, "fdc"),
 		m_floppy0(*this, "fdc:0"),
+		m_floppy1(*this, "fdc:1"),
 		m_rtc(*this, "rtc")
 	{
 	}
@@ -77,6 +78,7 @@ private:
 	required_device<com8116_device> m_brg;
 	required_device<fd1797_t> m_fdc;
 	required_device<floppy_connector> m_floppy0;
+	required_device<floppy_connector> m_floppy1;
 	required_device<msm5832_device> m_rtc;
 };
 
@@ -138,41 +140,46 @@ d7     XMEMEX line (for external memory, not emulated)
 WRITE8_MEMBER( pulsar_state::ppi_pa_w )
 {
 	m_floppy = nullptr;
-	if (BIT(data, 0)) m_floppy = m_floppy0->get_device();
+	if (BIT(data, 0))
+		m_floppy = m_floppy0->get_device();
+	else
+	if (BIT(data, 1))
+		m_floppy = m_floppy1->get_device();
 	m_fdc->set_floppy(m_floppy);
 	m_fdc->dden_w(BIT(data, 5));
+	if (m_floppy)
+		m_floppy->mon_w(0);
 }
 
 /*
 d0..d3 RTC address
-d4     RTC read line (inverted in emulation)
-d5     RTC write line (inverted in emulation)
+d4     RTC read line
+d5     RTC write line
 d6     RTC hold line
 d7     Allow 64k of ram
 */
 WRITE8_MEMBER( pulsar_state::ppi_pb_w )
 {
 	m_rtc->address_w(data & 0x0f);
-	m_rtc->read_w(!BIT(data, 4));
-	m_rtc->write_w(!BIT(data, 5));
+	m_rtc->read_w(BIT(data, 4));
+	m_rtc->write_w(BIT(data, 5));
 	m_rtc->hold_w(BIT(data, 6));
 	membank("bankr1")->set_entry(BIT(data, 7));
 }
 
-/*
-d0..d3 Data lines to rtc
-d7     /2 SIDES (assumed to be side select)
-*/
+// d0..d3 Data lines to rtc
 WRITE8_MEMBER( pulsar_state::ppi_pc_w )
 {
 	m_rtc->data_w(space, 0, data & 15);
-	if (m_floppy)
-		m_floppy->ss_w(BIT(data, 7));
 }
 
+// d7     /2 SIDES
 READ8_MEMBER( pulsar_state::ppi_pc_r )
 {
-	return m_rtc->data_r(space, 0);
+	uint8_t data = 0;
+	if (m_floppy)
+		data = m_floppy->twosid_r() << 7;
+	return m_rtc->data_r(space, 0) | data;
 }
 
 static DEVICE_INPUT_DEFAULTS_START( terminal )
@@ -185,7 +192,8 @@ static DEVICE_INPUT_DEFAULTS_START( terminal )
 DEVICE_INPUT_DEFAULTS_END
 
 static SLOT_INTERFACE_START( pulsar_floppies )
-	SLOT_INTERFACE( "525dd", FLOPPY_525_DD )
+	SLOT_INTERFACE( "drive0", FLOPPY_525_HD )
+	SLOT_INTERFACE( "drive1", FLOPPY_525_HD )
 SLOT_INTERFACE_END
 
 /* Input ports */
@@ -248,7 +256,10 @@ static MACHINE_CONFIG_START( pulsar, pulsar_state )
 	MCFG_COM8116_FT_HANDLER(WRITELINE(pulsar_state, ft_w))
 
 	MCFG_FD1797_ADD("fdc", XTAL_4MHz / 2)
-	MCFG_FLOPPY_DRIVE_ADD("fdc:0", pulsar_floppies, "525dd", floppy_image_device::default_floppy_formats)
+	MCFG_FLOPPY_DRIVE_ADD("fdc:0", pulsar_floppies, "drive0", floppy_image_device::default_floppy_formats)
+	MCFG_FLOPPY_DRIVE_SOUND(true)
+	MCFG_FLOPPY_DRIVE_ADD("fdc:1", pulsar_floppies, "drive1", floppy_image_device::default_floppy_formats)
+	MCFG_FLOPPY_DRIVE_SOUND(true)
 MACHINE_CONFIG_END
 
 /* ROM definition */
diff --git a/src/mame/drivers/qix.cpp b/src/mame/drivers/qix.cpp
index 4d2eb41..2a5db55 100644
--- a/src/mame/drivers/qix.cpp
+++ b/src/mame/drivers/qix.cpp
@@ -882,6 +882,24 @@ ROM_START( sdungeon )
 	ROM_LOAD( "sd101",    0x0000, 0x0800, CRC(e255af9a) SHA1(2410d3b7dec8e72a93d71c824c9403a6d96b9e8c) )
 ROM_END
 
+// same as above but uses larger ROMs
+ROM_START( sdungeona )
+	ROM_REGION( 0x10000, "maincpu", 0 )
+	ROM_LOAD( "1514.1J", 0xa000, 0x2000, CRC(8fe3e3c6) SHA1(f60acf7d2096a17726e89fee532fc68218657269) )
+	ROM_LOAD( "1716.1K", 0xc000, 0x2000, CRC(9976fe14) SHA1(759e966abaa3dd458c3d3f9ce5ef6abfec196d28) )
+	ROM_LOAD( "1819.1L", 0xe000, 0x2000, CRC(d56a40b0) SHA1(5b98e99938b6a394abca336995959cd97a55ddf7) )
+
+	ROM_REGION( 0x10000, "videocpu", 0 )
+	ROM_LOAD("65.1H",    0xa000, 0x2000, CRC(4b567837) SHA1(985e75829779cac366e57996016e5f949e1202c7) )
+	ROM_LOAD("87.1F",    0xc000, 0x2000, CRC(9298778b) SHA1(26c4dfd932e55e2525e46be8f58f26c67970d2bd) )
+	ROM_LOAD("109.1E",   0xe000, 0x2000, CRC(7437a6f1) SHA1(232fefb28c55338e5f3fed213ee94f44816241a0) )
+
+	ROM_REGION( 0x10000, "audiocpu", 0 )
+	ROM_LOAD( "2627.2D", 0xf000, 0x1000, CRC(1f830dff) SHA1(05b99d941d8fa53a4a9f9eb82e31d493d21d0f6f) )
+
+	ROM_REGION( 0x0800, "mcu", 0 )
+	ROM_LOAD( "sd101",   0x0000, 0x0800, CRC(e255af9a) SHA1(2410d3b7dec8e72a93d71c824c9403a6d96b9e8c) )
+ROM_END
 
 ROM_START( elecyoyo )
 	ROM_REGION( 0x10000, "maincpu", 0 )
@@ -1454,6 +1472,7 @@ GAME( 1981, qixb,     qix,      qix,      qix,      driver_device, 0,        ROT
 GAME( 1981, qixo,     qix,      qix,      qix,      driver_device, 0,        ROT270, "Taito America Corporation", "Qix (set 3, earlier)", MACHINE_SUPPORTS_SAVE ) // oldest set / prototype? has incorrect spelling 'deutch' and doesn't allow language selection to be changed
 GAME( 1981, qix2,     qix,      qix,      qix,      driver_device, 0,        ROT270, "Taito America Corporation", "Qix II (Tournament)", MACHINE_SUPPORTS_SAVE )
 GAME( 1981, sdungeon, 0,        mcu,      sdungeon, driver_device, 0,        ROT270, "Taito America Corporation", "Space Dungeon", MACHINE_SUPPORTS_SAVE ) // actually released July 1982
+GAME( 1981, sdungeona, sdungeon,mcu,      sdungeon, driver_device, 0,        ROT270, "Taito America Corporation", "Space Dungeon (larger roms)", MACHINE_SUPPORTS_SAVE ) // same as above but uses larger ROMs
 GAMEL(1982, elecyoyo, 0,        mcu,      elecyoyo, driver_device, 0,        ROT270, "Taito America Corporation", "The Electric Yo-Yo (set 1)", MACHINE_SUPPORTS_SAVE, layout_elecyoyo )
 GAMEL(1982, elecyoyo2,elecyoyo, mcu,      elecyoyo, driver_device, 0,        ROT270, "Taito America Corporation", "The Electric Yo-Yo (set 2)", MACHINE_SUPPORTS_SAVE, layout_elecyoyo )
 GAME( 1982, kram,     0,        mcu,      kram,     driver_device, 0,        ROT0,   "Taito America Corporation", "Kram (set 1)", MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/drivers/quizo.cpp b/src/mame/drivers/quizo.cpp
index bbac089..ca0e7a3 100644
--- a/src/mame/drivers/quizo.cpp
+++ b/src/mame/drivers/quizo.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /*********************************************
  Quiz Olympic (c)1985 Seoul Coin Corp.
diff --git a/src/mame/drivers/raiden.cpp b/src/mame/drivers/raiden.cpp
index 05bbd7c..d3bf1fa 100644
--- a/src/mame/drivers/raiden.cpp
+++ b/src/mame/drivers/raiden.cpp
@@ -10,13 +10,6 @@
     Raiden (Korean license)         (c) 1990 Seibu Kaihatsu
     Raiden (Taiwanese license)      (c) 1990 Seibu Kaihatsu
 
-    The alternate hardware version is probably newer than the main sets.
-    It looks closer to the newer 68000 games, while the main set looks
-    closer to Dynamite Duke (1989 game) in terms of graphics registers used, etc.
-
-    As well as different graphics registers the alternate set has a
-    different memory map, and different fix char layer memory layout!
-
     To access test mode, reset with both start buttons held.
 
     The country byte is stored at 0xffffd in the main cpu region,
@@ -37,14 +30,42 @@
     Sound: YM3812, OKI M6295
     Custom ICs:
     - SEI0160 QFP60 (2 on main PCB, 3 on OBJ1 PCB)
-    - S1S6091 QFP80 (4 on main PCB, 4 on OBJ1 PCB)
+    - S1S6091 or SEI0181 QFP80 (4 on main PCB, 4 on OBJ1 PCB)
     - Altera EP910PC-40 EPLD, one next to each V30
     - SEI0050BU DIP40
-    - SEI80BU DIP42
+    - SEI80BU DIP42 (next to encrypted Z80 ROM)
     - SEI0100BU "YM3931"
-    - many CMOS Gate Arrays
-
-    One of the sets is SEI8904 with SEI9008 subboard.
+    - SEI0010BU TC17G008AN-0025 (2 near mask ROMs, 1 near CHR ROMs)
+    - SEI0021BU TC17G008AN-0022 (4 between mask ROMs)
+    - SG0140 TC110G05AN-0012 (2)
+
+    The following alternate main PCB types have been observed:
+
+    1. "SEI8904 MAIN"; custom chips are similar to the common dedicated
+       hardware, but PCB layout is vastly different, resembling Dynamite
+       Duke (Seibu's previous game); the format of CHR RAM is transposed
+       here. One (undumped) set, perhaps the earliest revision of the game,
+       has a half-empty SEI8904-ROM subboard which has the BG and sprite
+       tiles in ROMs with even numbers starting at 20, 30, 40; another set
+       instead has a SEI9008 subboard that replaces these 12 ROMs with the
+       SEI420, SEI430 and SEI440 mask ROMs found on later non-bootleg sets.
+
+    2. Newer Seibu hardware, lacking the encryption PLDs and many of the
+       older-generation custom ICs listed above, though the mask ROMs and
+       OBJ1 subboard remain the same. The graphics registers here are very
+       different from previous licensed sets, having the CRTC-style format
+       of all subsequent Seibu arcade games.
+
+    3. Korean bootleg hardware, with no custom ICs and an enormous subboard
+       with four ROMs amidst over 100 TTL chips. (This is almost certainly
+       different from the dumped raidenk set, despite displaying the IBL
+       license on the title screen.)
+
+    On some boards (both the common dedicated hardware and the older
+    SEI8904), the SEI0050BU has been replaced with a small daughterboard
+    with six TTL chips and two PLDs labeled S50P01 and S50P02. A bootleg
+    set has been observed with a (larger) daughterboard likewise standing
+    in for a Xilinx PLD.
 
 ***************************************************************************/
 
@@ -561,6 +582,49 @@ ROM_START( raidenk ) /* Same board as above. Not sure why the sound CPU would be
 	ROM_LOAD( "7.u203", 0x00000, 0x10000, CRC(8f927822) SHA1(592f2719f2c448c3b4b239eeaec078b411e12dbb) )
 ROM_END
 
+ROM_START( raidenkb ) /* Korean bootleg board. ROMs for main, sub, audiocpu, chars and oki match raidenk, while object and tile ROMs are differently split */
+	ROM_REGION( 0x100000, "maincpu", 0 ) /* v30 main cpu */
+	ROM_LOAD16_BYTE( "1.u0253", 0x0a0000, 0x10000, CRC(a4b12785) SHA1(446314e82ce01315cb3e3d1f323eaa2ad6fb48dd) )
+	ROM_LOAD16_BYTE( "2.u0252", 0x0a0001, 0x10000, CRC(17640bd5) SHA1(5bbc99900426b1a072b52537ae9a50220c378a0d) )
+	ROM_LOAD16_BYTE( "3.u022",  0x0c0000, 0x20000, CRC(f6af09d0) SHA1(ecd49f3351359ea2d5cbd140c9962d45c5544ecd) )
+	ROM_LOAD16_BYTE( "4k.u023", 0x0c0001, 0x20000, CRC(fddf24da) SHA1(ececed0b0b96d070d85bfb6174029142bc96d5f0) ) /* 0x1fffd == 0x02, 0x1fffe == 0xA4 */
+
+	ROM_REGION( 0x100000, "sub", 0 ) /* v30 sub cpu */
+	ROM_LOAD16_BYTE( "5.u042", 0x0c0000, 0x20000, CRC(ed03562e) SHA1(bf6b44fb53fa2321cd52c00fcb43b8ceb6ceffff) )
+	ROM_LOAD16_BYTE( "6.u043", 0x0c0001, 0x20000, CRC(a19d5b5d) SHA1(aa5e5be60b737913e5677f88ebc218302245e5af) )
+
+	ROM_REGION( 0x20000, "audiocpu", 0 ) /* 64k code for sound Z80 */
+	ROM_LOAD( "8b.u212",     0x000000, 0x08000, CRC(99ee7505) SHA1(b97c8ee5e26e8554b5de506fba3b32cc2fde53c9) ) /* Not encrypted */
+	ROM_CONTINUE(            0x010000, 0x08000 )
+	ROM_COPY( "audiocpu", 0x000000, 0x018000, 0x08000 )
+
+	ROM_REGION( 0x010000, "gfx1", 0 ) /* Chars */
+	ROM_LOAD( "9",  0x00000, 0x08000, CRC(1922b25e) SHA1(da27122dd1c43770e7385ad602ef397c64d2f754) ) /* On some PCBs there is no explicit */
+	ROM_LOAD( "10", 0x08000, 0x08000, CRC(5f90786a) SHA1(4f63b07c6afbcf5196a433f3356bef984fe303ef) ) /* U location for these two roms     */
+
+	ROM_REGION( 0x080000, "gfx2", 0 ) /* tiles */
+	ROM_LOAD16_BYTE( "rkb15bg.bin", 0x00000, 0x20000, CRC(13a69064) SHA1(a9fcd785e3bac7c0d39be532b3755e6dd45fc314) )
+	ROM_LOAD16_BYTE( "rkb17bg.bin", 0x00001, 0x20000, CRC(d7a6c649) SHA1(01d6f18af0385466e3956c3f3afc82393acee6bc) )
+	ROM_LOAD16_BYTE( "rkb16bg.bin", 0x40000, 0x20000, CRC(66ea8484) SHA1(f4452e1b0991bf81a60b580ba822fc43b1a443e6) )
+	ROM_LOAD16_BYTE( "rkb18bg.bin", 0x40001, 0x20000, CRC(42362d56) SHA1(1cad19fa3f66e34865383d9a94e9058114910365) )
+
+	ROM_REGION( 0x080000, "gfx3", 0 ) /* tiles */
+	ROM_LOAD16_BYTE( "rkb7bg.bin",  0x00000, 0x20000, CRC(25239711) SHA1(978cfc6487ed711cc1b513824741c347ec92889d) )
+	ROM_LOAD16_BYTE( "rkb9bg.bin",  0x00001, 0x20000, CRC(6ca0d7b3) SHA1(ef63657a01b07aaa0ded7b0d405b872b4d3a56a8) )
+	ROM_LOAD16_BYTE( "rkb8bg.bin",  0x40000, 0x20000, CRC(3cad38fc) SHA1(de2257f70c3e71905bc959f80be183c6d95fd06d) )
+	ROM_LOAD16_BYTE( "rkb10bg.bin", 0x40001, 0x20000, CRC(6fce95a3) SHA1(1d3beda3a4dd0a2a3afbb7b5b16d87bf3257bcb4) )
+
+
+	ROM_REGION( 0x090000, "gfx4", 0 ) /* sprites */
+	ROM_LOAD16_BYTE( "rkb19obj.bin", 0x00000, 0x20000, CRC(34fa4485) SHA1(d9893c484ee4f80e364824500c6c048f58f49752) )
+	ROM_LOAD16_BYTE( "rkb21obj.bin", 0x00001, 0x20000, CRC(d806395b) SHA1(7c6fc848aa40a49590e00d0b02ce21ad5414e387) )
+	ROM_LOAD16_BYTE( "rkb20obj.bin", 0x40000, 0x20000, CRC(8b7ca3c6) SHA1(81c3e98cbd81a39e04b5e7fb3683aba50545f774) )
+	ROM_LOAD16_BYTE( "rkb22obj.bin", 0x40001, 0x20000, CRC(82ee78a0) SHA1(4af0593f9c7d8db59f17d75d6f9020ecd4bdcb98) )
+
+	ROM_REGION( 0x40000, "oki", 0 )  /* ADPCM samples */
+	ROM_LOAD( "7.u203", 0x00000, 0x10000, CRC(8f927822) SHA1(592f2719f2c448c3b4b239eeaec078b411e12dbb) )
+ROM_END
+
 ROM_START( raidenb )/* Different hardware, Main & Sub CPU code not encrypted. */
 	ROM_REGION( 0x100000, "maincpu", 0 ) /* v30 main cpu */
 	ROM_LOAD16_BYTE( "1.u0253", 0x0a0000, 0x10000, CRC(a4b12785) SHA1(446314e82ce01315cb3e3d1f323eaa2ad6fb48dd) )
@@ -681,8 +745,11 @@ GAME( 1990, raident,  raiden, raidene, raiden, raiden_state,  raiden,  ROT270, "
 /* Same as above, but the sound CPU code is not encrypted */
 GAME( 1990, raidenk,  raiden, raiden,  raiden, raiden_state,  raiden,  ROT270, "Seibu Kaihatsu (IBL Corporation license)", "Raiden (Korea)", MACHINE_SUPPORTS_SAVE )
 
+/* Bootleg of the Korean release */
+GAME( 1990, raidenkb, raiden, raiden,  raiden, raiden_state,  raiden,  ROT270, "bootleg", "Raiden (Korea, bootleg)", MACHINE_SUPPORTS_SAVE )
+
 /* Alternate hardware; SEI8904 + SEI9008 PCBs. Main & Sub CPU code not encrypted */
 GAME( 1990, raidenua, raiden, raidenu, raiden, driver_device, 0,       ROT270, "Seibu Kaihatsu (Fabtek license)", "Raiden (US set 2)", MACHINE_SUPPORTS_SAVE )
 
-/* Alternate hardware. Main, Sub & Sound CPU code not encrypted - could possibly be a bootleg?? It also sports Seibu custom CRTC. */
+/* Alternate hardware. Main, Sub & Sound CPU code not encrypted. It also sports Seibu custom CRTC. */
 GAME( 1990, raidenb,  raiden, raidenb, raiden, driver_device, 0,       ROT270, "Seibu Kaihatsu", "Raiden (set 3)", MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/drivers/rainbow.cpp b/src/mame/drivers/rainbow.cpp
index 6fac84a..1e7df99 100644
--- a/src/mame/drivers/rainbow.cpp
+++ b/src/mame/drivers/rainbow.cpp
@@ -8,7 +8,7 @@
 // - Registers of graphics option not directly mapped (indirect access via mode register)
 // - write mask is 16 bits wide (not only 8)
 // - scroll register is 8 bits wide - not 16.
-// - no "DMA SCROLL", "LINE ERASE MODE", no ZOOM hardware (factor must always be 1)
+// - no "LINE ERASE MODE", 7220 DMA lines are unused. No ZOOM hardware (factor must always be 1)
 
 // Two modes: highres and medres mode (different bank length..?)
 // - MEDRES: palette of 16 colors out of 4096.   384 x 240
@@ -34,36 +34,40 @@ SCREEN 1 vs. SCREEN 2 IN EMULATION
 // The type of monochrome monitor (VR-210 A, B or C) is selectable via another DIP (coarsly simulates a phosphor color).
 
 BUGS
-- MEDRES LOOKS CORRECT
-- HIRES-MODE SEMI BROKEN (colors OK, else untested).
-- GDC diagnostic disk bails out on 10 of 13 low level tests. Separate SCROLL CHECK crashes CPU. Readback from GDC fails?
-- VECTOR MODE SEEMS TO DISPLAY NOTHING AT ALL (16 bit access botched here in driver?)
-Interaction of Upd7220 and Rainbow.cpp:
-- FIG directions / params appear to be odd (lines go 45 degrees up or down instead of straight dir.),
-- RDAT with MOD 2 is unimplemented. WDAT appears to set "m_bitmap_mod" wrongly ("2" means all pixels will be reset)...
-Freeware to try: MMIND (MasterMind, after BMP logo), SOLIT (Solitaire), CANON (high resolution + vectors).
+- GDC diagnostic disk fails on 9 of 13 tests (tests 4 and 6 - 13).
+
+Details
+a. (Rainbow driver) : interaction between DEC's external hardware and the NEC 7220 isn't fully understood (see page 173 of AA-AE36A)
+   It is also unclear what port $50 actually does when it 'synchronizes R-M-W cycles'.
+   For now, we provide sane defaults for both vector and bitmap units without disturbing display mode(s) or the NEC 7220.
+b. the HBLANK / VBLANK ratio is plainly wrong (quick test / subtest #6),
+c. IRQs are flagged as 'erratic' (quick test / subtest #12).
+d. (7220) : incorrect fifo stati are handed out (GDC reports FIFO_EMPTY instead of _FULL when quick test #4 floods the queue)
+e. (7220) : RDAT with MOD 2 used extensively here, but unimplemented (modes other than 0 undocumented by NEC / Intel)
 
 UNIMPLEMENTED:
-// - Rainbow 100 A palette quirks (2 bit palette... applies to certain modes only)
+- Rainbow 100 A palette quirks (2 bit palette... applies to certain modes only)
 
 UNKNOWN IMPLEMENTATION DETAILS:
-// a. READBACK (hard copy programs like JOBSDUMP definitely use it. See also GDC diagnostics).  VRAM_R ?
+1. READBACK (hard copy programs like JOBSDUMP definitely use it. See also GDC diagnostics).  VRAM_R ?
+
+2. UNVERIFIED DIVIDERS (31.188 Mhz / 32) is at least close to 1 Mhz (as on the VT240, which uses a very similar design)
+
+3. UPD7220 / CORE oddities
 
-// b. SCROLL BUFFER initialization (details) unclear. What happens when a programs does not write all 256 bytes? Value of uninitialized areas?
-   Play, then retry (y) SCRAM to see the effect. Scram doesn't seem to write all (256) bytes, a GDC RESET is only executed at startup...
-   (PAGE 48 OF PDF HAS A SUPERFICIAL DESCRIPTION OF THE SCROLL BUFFER)
+To obtain pixel exact graphics use 'Graphics Only' in Video Options  plus command line switches -nowindow -aspect1 auto -nokeepaspect
+(Over-Under or Side-by-Side modes always distorted on my 1600 x 900 laptop)
 
-// c. UNVERIFIED XTAL / CLOCK:
-// There is a 31.188 Mhz crystal in DUELL's hand written Option Graphics circuit (not to be found in XTAL).
-// According to the datasheet, the NEC 7220 was certified for  4.0 , 5.0, and 5.5 Mhz and the 7220A for 6.0, 7.0, and 8.0 Mhz
+Programs with initialization / redraw / reentrance problems (invocation order after reset matters in emulation):
 
-// d. UPD7220 oddities: * refresh rate much too fast at 32Mhz/4 (Upd7220 LOG says 492 Mhz?!).
-//                      * pixels are stretched out too wide at 384 x 240. Compare the real SCRAM screenshot online!
+- CANON (high resolution + vectors), Solitaire (SOLIT.EXE) and GDEMO (from GRPHCS.ARC, interactive graphics interpreter '85),
+  plus 'Monitor Aligment' (from the GDC test disk).             Sloppy programming or a bug related to a) to e)...?
 
-// e. FIXME (MAME/MESS): what happens when the left screen is at 50 Hz and the right at 60 Hz?
-//  According to Haze: "if you have 2 screens running at different refresh rates one of them won't update properly
-//  (the partial update system gets very confused because it expects both the screens to end at the same time
-//  and if that isn't the case large parts of one screen end up not updating at all)
+ Quote from Haze: "if you have 2 screens running at different refresh rates one of them won't update properly
+                    (the partial update system gets very confused because it expects both the screens to end at the same time
+                    and if that isn't the case large parts of one screen end up not updating at all)
+
+The following games work well: MMIND (MasterMind), (G)OTELO (requires GSX), PACMAN, SCRAM (last one uses scroll extensively).
 */
 
 // license:GPL-2.0+
@@ -72,7 +76,7 @@ UNKNOWN IMPLEMENTATION DETAILS:
 DEC Rainbow 100
 
 Driver-in-progress by R. Belmont and Miodrag Milanovic.
-Keyboard fix by Cracyc (June 2016), Baud rate generator by Shattered (July 2016)
+Keyboard & GDC fixes by Cracyc (June - Nov. 2016), Baud rate generator by Shattered (July 2016)
 Portions (2013 - 2016) by Karl-Ludwig Deisenhofer (Floppy, ClikClok RTC, NVRAM, DIPs, hard disk, Color Graphics).
 
 To unlock floppy drives A-D compile with WORKAROUND_RAINBOW_B (prevents a side effect of ERROR 13).
@@ -92,8 +96,8 @@ PLEASE USE THE RIGHT SLOT - AND ALWAYS SAVE YOUR DATA BEFORE MOUNTING FOREIGN DI
 You * should * also reassign SETUP (away from F3, where it sits on a LK201).
 DATA LOSS POSSIBLE: when in partial emulation mode, F3 performs a hard reset!
 
-STATE AS OF OCTOBER 2016
-------------------------
+STATE AS OF DECEMBER 2016
+-------------------------
 Driver is based entirely on the DEC-100 'B' variant (DEC-190 and DEC-100 A models are treated as clones).
 While this is OK for the compatible -190, it doesn't do justice to ancient '100 A' hardware.
 The public domain file RBCONVERT.ZIP documents how model 'A' differs from version B.
@@ -117,16 +121,14 @@ Some BUGS remain: BIOS autoboot doesnt work at all. It is not possible to boot f
 CTRL-SETUP (soft reboot) always triggers ERROR 19 (64 K RAM err.). One explanation is that ZFLIP/ZRESET is
 handled wrongly, so shared mem. just below $8000 is tainted by Z80 stack data. A reentrance problem?
 
-Occassionally, ERROR 13 for keyboard stuck or ERROR 27 for RAM BOARD error appear (for reasons yet unknown).
+Occassionally, ERROR 13 -keyboard stuck- appears (for reasons yet unknown).
 
 CURRENTY UNEMULATED
 -------------------
-(a) the serial port does work one way only (incomplete null modem or wiring?), no reception yet.
- The printer interface does not work, so a non fatal ERROR 40 (serial printer interface) will appear.
+(a) the serial printer on port B prints garbage. It is worth to mention that port B relies on XON/XOFF,
+    while DTR_L (CTS B) means 'printer ready'. There is also a ROM patch in place (WORKAROUND macro)...
 
-(b1) LOOPBACK circuit not emulated, NMI from RAM card also unemulated (NMI vector 02).
-The former is used in startup tests, the latter seems less relevant (must use menu self test "S"
- or memory diagnostic test. TODO: mem.test causes a CPU crash when reaching higher RAM regions.
+(b1) LOOPBACK circuit not emulated (used in startup tests).
 
 (b2) system interaction tests HALT Z80 CPU at location $0211 (forever). Boot the RX50 diag.disk
  to see what happens (key 3 - individual tests, then 12 - system interaction). Uses LOOPBACK too?
@@ -303,27 +305,39 @@ W17 pulls J1 serial  port pin 1 to GND when set (chassis to logical GND).
 ****************************************************************************/
 #define RD51_MAX_HEAD 8
 #define RD51_MAX_CYLINDER 1024
-#define RD51_SECTORS_PER_TRACK 17 // OLD: #define RD51_SECTORS_PER_TRACK 16
-
-#define RTC_BASE 0xFC000
-// Do not pretend to emulate newer RAM board; stick with the old one:
-// (only affects presence bit in 'system_parameter_r')
-#define OLD_RAM_BOARD_PRESENT
-
+#define RD51_SECTORS_PER_TRACK 17
+
+#define RTC_ENABLED
+// Tested drivers (from Suitable Solutions distribution disk and Latrobe archive), preferred first -
+// File.........Version / author ------------------- YY/YYYY ----- Read only RTC_BASE ---- Platform
+// RBCLIK21.COM Author: Vincent Esser. With source.. 4 digits (Y2K)..Y.......$fc000/fe000..100-B (default cfg.)
+// CLIKA.COM .. V1.03A (C) 1987 Suitable Solutions.. 2 digits........N (*)...$ed000........100-A
+// CLIKCLOK.COM V1.01 (C) 1986,87 Suitable Solutions 2 digits........N (*)...$fc000/fe000..100-B (default   " )
+// CLIKF4.COM . V1.0  (C) 1986 Suitable Solutions... 2 digits........N (*)...$f4000........100-B (alternate " )
+// (*)   Time or date changes are not persistent in emulation. To prove the setter works, changes are logged.
+
+// (Y2K) DS1315 unit only holds 2 digits, so Vincent Esser's freeware employs a windowing technique.
+//       While Suitable's DOS 3.10 accepts dates > 2000, don't take that for granted with software from the 80s.
 #ifdef      ASSUME_MODEL_A_HARDWARE
+	#define RTC_BASE 0xED000
+
 	// Define standard and maximum RAM sizes (A model):
 	#define MOTHERBOARD_RAM 0x0ffff  // 64 K base RAM  (100-A)
 	#define END_OF_RAM 0xcffff // Very last byte (theretical; on 100-A) DO NOT CHANGE.
+
+	// Pretend to emulate older RAM board (no NMI, also affects presence bit in 'system_parameter_r'):
+	#define OLD_RAM_BOARD_PRESENT
 #else
+	#define RTC_BASE 0xFC000 // (default configuration, also covers FE000+)
+//  #define RTC_BASE 0xF4000 // (alternate configuration) - ClikClok V1.0 / CLIKF4.COM
+
 	// DEC-100-B probes until a 'flaky' area is found (BOOT ROM around F400:0E04).
 	// It is no longer possible to key in the RAM size from within the 100-B BIOS.
 	#define MOTHERBOARD_RAM 0x1ffff  // 128 K base RAM (100-B)
 	#define END_OF_RAM 0xdffff // very last byte (100-B theoretical max.) DO NOT CHANGE.
 
 	#define WORKAROUND_RAINBOW_B // work around DRIVE ERROR (tested on 100-B ROM only)
-
-	#define RTC_ENABLED
-#endif
+ #endif
 
 // ----------------------------------------------------------------------------------------------
 // * MHFU disabled by writing a _sensible_ value to port 0x10C (instead of port 0x0c)
@@ -455,7 +469,8 @@ public:
 		m_hdc(*this, "hdc"),
 
 		m_mpsc(*this, "upd7201"),
-		m_dbrg(*this, "com8116"),
+		m_dbrg_A(*this, "com8116_a"),
+		m_dbrg_B(*this, "com8116_b"),
 
 		m_kbd8251(*this, "kbdser"),
 		m_lk201(*this, LK201_TAG),
@@ -466,6 +481,7 @@ public:
 		m_p_nvram(*this, "nvram"),
 
 		m_shared(*this, "sh_ram"),
+		m_ext_ram(*this, "ext_ram"),
 
 		m_rtc(*this, "rtc"),
 		m_hgdc(*this, "upd7220"), // GDC-NEW
@@ -534,12 +550,17 @@ public:
 	DECLARE_READ8_MEMBER(rtc_reset);
 	DECLARE_READ8_MEMBER(rtc_enable);
 	DECLARE_READ8_MEMBER(rtc_r);
+	DECLARE_WRITE8_MEMBER(rtc_w);
+
+	DECLARE_WRITE8_MEMBER(ext_ram_w);
 
 	DECLARE_WRITE_LINE_MEMBER(mpsc_irq);
 	DECLARE_WRITE8_MEMBER(comm_bitrate_w);
 	DECLARE_WRITE8_MEMBER(printer_bitrate_w);
 	DECLARE_WRITE_LINE_MEMBER( com8116_a_fr_w );
 	DECLARE_WRITE_LINE_MEMBER( com8116_a_ft_w );
+	DECLARE_WRITE_LINE_MEMBER( com8116_b_fr_w );
+	DECLARE_WRITE_LINE_MEMBER( com8116_b_ft_w );
 
 	DECLARE_WRITE8_MEMBER(GDC_EXTRA_REGISTER_w);
 	DECLARE_READ8_MEMBER(GDC_EXTRA_REGISTER_r);
@@ -599,13 +620,15 @@ private:
 	optional_device<wd2010_device> m_hdc;
 
 	required_device<upd7201_device> m_mpsc;
-	required_device<com8116_device> m_dbrg;
+	required_device<com8116_device> m_dbrg_A;
+	required_device<com8116_device> m_dbrg_B;
 	required_device<i8251_device> m_kbd8251;
 	required_device<lk201_device> m_lk201;
 	required_shared_ptr<uint8_t> m_p_ram;
 	required_shared_ptr<uint8_t> m_p_vol_ram;
 	required_shared_ptr<uint8_t> m_p_nvram;
 	required_shared_ptr<uint8_t> m_shared;
+	required_shared_ptr<uint8_t> m_ext_ram;
 
 	optional_device<ds1315_device> m_rtc;
 
@@ -630,7 +653,6 @@ private:
 
 	uint8_t m_GDC_WRITE_BUFFER[16]; // 16 x 8 bits for CPU, 8 x 16 for GDC
 	uint8_t m_GDC_COLOR_MAP[32];
-	uint8_t m_GDC_SCROLL_BUFFER_PRELOAD[256];
 	uint8_t m_GDC_SCROLL_BUFFER[256];
 
 	uint8_t  m_GDC_INDIRECT_REGISTER, m_GDC_MODE_REGISTER, m_GDC_scroll_index, m_GDC_color_map_index, m_GDC_write_buffer_index;
@@ -638,7 +660,7 @@ private:
 	uint8_t  m_vpat, m_patmult, m_patcnt, m_patidx;
 
 	uint16_t m_GDC_WRITE_MASK;
-	bool m_scroll_buffer_changed, m_color_map_changed;
+	bool m_color_map_changed;
 	bool m_ONBOARD_GRAPHICS_SELECTED;   // (internal switch, on board video to mono out)
 
 	bool m_SCREEN_BLANK;
@@ -696,25 +718,35 @@ private:
 };
 
 
+// It * should be * OK to RESET the SCROLL_BUFFER and the COLOR_MAP (at least with WELL WRITTEN programs)
+
+// Situation less clear for vector mode (some programs work extensively * before * OPTION_GRFX_RESET
+
+// THIS MACRO * RESETS *  the PATTERN TO DEFAULT.
+// NOTE 2: m_patmult  MUST BE LOADED BEFORE !!
+#define OPTION_RESET_PATTERNS \
+m_vpat = 0xff;                \
+if(m_patmult == 0)  m_patmult = 0x01;\
+if(m_patcnt == 0)   m_patcnt = m_patmult;\
+if(m_patidx == 0)   m_patidx = 7;
+
+
 // GDC RESET MACRO - used in  "machine_reset"  & GDC_EXTRA_REGISTER_w   !
-#define GDC_RESET_MACRO                                     \
+#define OPTION_GRFX_RESET                                   \
+lower_8088_irq(IRQ_GRF_INTR_L);                             \
 m_PORT50 = 0;                                               \
 m_GDC_INDIRECT_REGISTER = 0;                                \
-m_GDC_MODE_REGISTER = 0;                                    \
-m_GDC_WRITE_MASK = 0;                                       \
-m_GDC_write_buffer_index = 0;                               \
 m_GDC_color_map_index = 0;                                  \
-m_GDC_ALU_PS_REGISTER = 0;                                  \
-m_vpat  = 0;                                                \
-m_patmult = 1;                                              \
-m_patcnt = 0;                                               \
-m_patidx  = 7;                                              \
-m_GDC_FG_BG = 0;                                            \
 m_color_map_changed = true;                                 \
-for(int i=0; i <256; i++) { m_GDC_SCROLL_BUFFER[i] = m_GDC_SCROLL_BUFFER_PRELOAD[i] = i; };\
-m_GDC_scroll_index = 255;                                   \
-m_scroll_buffer_changed = true;                             \
-printf("\n** NEC 7220 GDC RESET **\n");
+for(int i=0; i <256; i++) { m_GDC_SCROLL_BUFFER[i] = i; };  \
+m_GDC_scroll_index = 0;                                     \
+m_GDC_write_buffer_index = 0;                               \
+m_GDC_WRITE_MASK = 0x00;                                    \
+m_GDC_ALU_PS_REGISTER = 0x0F;                               \
+m_GDC_FG_BG = 0xF0;                                         \
+m_GDC_MODE_REGISTER &= GDC_MODE_VECTOR | GDC_MODE_HIGHRES | GDC_MODE_ENABLE_WRITES | GDC_MODE_READONLY_SCROLL_MAP;\
+m_GDC_MODE_REGISTER |= GDC_MODE_ENABLE_VIDEO;               \
+printf("\n** OPTION GRFX. RESET **\n");
 
 UPD7220_DISPLAY_PIXELS_MEMBER( rainbow_state::hgdc_display_pixels )
 {
@@ -733,25 +765,33 @@ UPD7220_DISPLAY_PIXELS_MEMBER( rainbow_state::hgdc_display_pixels )
 	uint16_t plane0, plane1, plane2, plane3;
 	uint8_t pen;
 
-	if(!(m_GDC_MODE_REGISTER & GDC_MODE_ENABLE_VIDEO))
+	if(m_ONBOARD_GRAPHICS_SELECTED && (m_inp13->read() != DUAL_MONITOR) )
+	{
+		for(xi=0;xi<16;xi++) // blank screen when VT102 output active (..)
+		{
+			if (bitmap.cliprect().contains(x + xi, y))
+				bitmap.pix32(y, x + xi) = 0;
+		}
 		return; // no output from graphics option
+	}
 
 	// ********************* GET BITMAP DATA FOR 4 PLANES ***************************************
 	// _READ_ BIT MAP  from 2 or 4 planes (plane 0 is least, plane 3 most significant). See page 42 / 43
 	if(m_GDC_MODE_REGISTER & GDC_MODE_HIGHRES)
 	{
-			plane0 = m_video_ram[((address & 0x7fff) + 0x00000) >> 1];
-			plane1 = m_video_ram[((address & 0x7fff) + 0x10000) >> 1];
-			plane2 = plane3 = 0;
+		address = ( m_GDC_SCROLL_BUFFER[ ((address & 0x7FC0) >> 7) & 0xff ] << 7) |  (address & 0x7F);
+		plane0 = m_video_ram[((address & 0x7fff) + 0x00000) >> 1];
+		plane1 = m_video_ram[((address & 0x7fff) + 0x10000) >> 1];
+		plane2 = plane3 = 0;
 	}
-		else
+	else
 	{
-			// MED.RESOLUTION (4 planes, 4 color bits, 16 color map entries / 16 (4) MONOCHROME SHADES)
-			// MANUAL SAYS:   (GDC "sees" 4 planes X 16 bits X 8K words)!
-			plane0 = m_video_ram[((address & 0x3fff) + 0x00000) >> 1];
-			plane1 = m_video_ram[((address & 0x3fff) + 0x10000) >> 1];
-			plane2 = m_video_ram[((address & 0x3fff) + 0x20000) >> 1];
-			plane3 = m_video_ram[((address & 0x3fff) + 0x30000) >> 1];
+		address = ( m_GDC_SCROLL_BUFFER[ ((address & 0x3FC0) >> 7) & 0xff ] << 7) |  (address & 0x7F);
+		// MED.RESOLUTION (4 planes, 4 color bits, 16 color map entries / 16 -or 4- MONOCHROME SHADES)
+		plane0 = m_video_ram[((address & 0x3fff) + 0x00000) >> 1];
+		plane1 = m_video_ram[((address & 0x3fff) + 0x10000) >> 1];
+		plane2 = m_video_ram[((address & 0x3fff) + 0x20000) >> 1];
+		plane3 = m_video_ram[((address & 0x3fff) + 0x30000) >> 1];
 	}
 
 	bool mono = (m_inp13->read() == MONO_MONITOR) ? true : false; // 1 = MONO, 2 = COLOR, 3 = DUAL MONITOR
@@ -809,9 +849,13 @@ void rainbow_state::machine_start()
 	if (rom[0xf4000 + 0x3ffc] == 0x31) // 100-B (5.01)    0x35 would test for V5.05
 	{
 		rom[0xf4000 + 0x0303] = 0x00; // disable CRC check
-		rom[0xf4000 + 0x135e] = 0x00; // FLOPPY / RX-50 WORKAROUND: in case of Z80 RESPONSE FAILURE ($80 bit set in AL), do not block floppy access.
+		rom[0xf4000 + 0x135e] = 0x00; // Floppy / RX-50 workaround: in case of Z80 RESPONSE FAILURE ($80 bit set in AL), do not block floppy access.
 
 		rom[0xf4000 + 0x198F] = 0xeb; // cond.JMP to uncond.JMP (disables error message 60...)
+
+		rom[0xf4000 + 0x315D] = 0x00; // AND DL,0 (make sure DL is zero before ROM_Initialize7201)
+		rom[0xf4000 + 0x315E] = 0xe2;
+		rom[0xf4000 + 0x315F] = 0x02;
 	}
 #endif
 }
@@ -819,12 +863,12 @@ void rainbow_state::machine_start()
 static ADDRESS_MAP_START(rainbow8088_map, AS_PROGRAM, 8, rainbow_state)
 ADDRESS_MAP_UNMAP_HIGH
 AM_RANGE(0x00000, 0x0ffff) AM_RAM AM_SHARE("sh_ram")
-AM_RANGE(0x10000, END_OF_RAM) AM_RAM
+AM_RANGE(0x10000, END_OF_RAM) AM_RAM AM_SHARE("ext_ram") AM_WRITE(ext_ram_w)
 
 // There is a 2212 (256 x 4 bit) NVRAM from 0xed000 to 0xed0ff (*)
 // shadowed at $ec000 - $ecfff and from $ed100 - $edfff.
 
-// (*) ED000 - ED0FF is the area the DEC-100-B BIOS accesses and checks
+// (*) ED000 - ED0FF is the area the DEC-100-B Bios accesses and checks
 
 //  - Specs say that the CPU has direct access to volatile RAM only.
 //    So NVRAM is hidden and loads & saves are triggered within the
@@ -1046,6 +1090,10 @@ INPUT_PORTS_END
 
 void rainbow_state::machine_reset()
 {
+	// 'F3' (in partial emulation) here replaces 'CTRL-SETUP' (soft reboot on an original Rainbow)
+	// FIXME: BIOS reports error 19 when CTRL-SETUP is pressed (Z80 or flags aren't fully reset then?)
+	popmessage("Reset");
+
 	// Configure RAM
 	address_space &program = machine().device<cpu_device>("maincpu")->space(AS_PROGRAM);
 	uint32_t unmap_start = m_inp8->read();
@@ -1063,8 +1111,16 @@ void rainbow_state::machine_reset()
 		printf("\nWARNING: 896 K is not a valid memory configuration on Rainbow 100 A!\n");
 	}
 
-//  check = (unmap_start >> 16)-1;  // guess.
-//  NVRAM_LOCATION = nv[0xed084];   // location not verified yet. DMT RAM check tests offset $84 !
+	check = (unmap_start >> 16)-1;  // guess.
+	NVRAM_LOCATION = nv[0xed084];   // location not verified yet. DMT RAM check tests offset $84 !
+
+	#ifdef RTC_ENABLED
+	// *********************************** / DS1315 'PHANTOM CLOCK' IMPLEMENTATION FOR 'DEC-100-A' ***************************************
+	program.install_read_handler(RTC_BASE, RTC_BASE, read8_delegate(FUNC(rainbow_state::rtc_r), this));
+	program.install_write_handler(RTC_BASE + 0xFE, RTC_BASE + 0xFF, write8_delegate(FUNC(rainbow_state::rtc_w), this));
+	// *********************************** / DS1315 'PHANTOM CLOCK' IMPLEMENTATION FOR 'DEC-100-A' ***************************************
+	#endif
+
 #else
 	printf("\n*** RAINBOW B MODEL ASSUMED (128 - 896 K RAM)\n");
 	if (unmap_start < 0x20000)
@@ -1075,25 +1131,27 @@ void rainbow_state::machine_reset()
 
 	check = (unmap_start >> 16) - 2;
 	NVRAM_LOCATION = nv[0xed0db];
+
+	#ifdef RTC_ENABLED
+	// *********************************** / DS1315 'PHANTOM CLOCK' IMPLEMENTATION FOR 'DEC-100-B' ***************************************
+	// No address space needed ( -> IRQs must be disabled to block ROM accesses during reads ).
+	program.install_read_handler(RTC_BASE, RTC_BASE + 0x2104, read8_delegate(FUNC(rainbow_state::rtc_r), this));
+	// *********************************** / DS1315 'PHANTOM CLOCK' IMPLEMENTATION FOR 'DEC-100-B' ***************************************
+	#endif
 #endif
 	if (check != NVRAM_LOCATION)
 		printf("\nNOTE: RAM configuration does not match NVRAM.\nUNMAP_START = %05x   NVRAM VALUE = %02x   SHOULD BE: %02x\n", unmap_start, NVRAM_LOCATION, check);
 
 	if(END_OF_RAM > unmap_start)
+	{
+		printf("\nUnmapping from %x to %x",unmap_start, END_OF_RAM);
 		program.unmap_readwrite(unmap_start, END_OF_RAM);
+	}
 
 	m_crtc->MHFU(MHFU_RESET_and_DISABLE);
 
-#ifdef RTC_ENABLED
-// *********************************** / DS1315 'PHANTOM CLOCK' IMPLEMENTATION FOR 'DEC-100-B' ***************************************
-// No address space needed ( -> IRQs must be disabled to block ROM accesses during reads ).
-	program.install_read_handler(RTC_BASE, RTC_BASE + 0x2104, read8_delegate(FUNC(rainbow_state::rtc_r), this));
-// *********************************** / DS1315 'PHANTOM CLOCK' IMPLEMENTATION FOR 'DEC-100-B' ***************************************
-#endif
-
 	m_rtc->chip_reset();     // * Reset RTC to a defined state *
 
-
 	//  *********** HARD DISK CONTROLLER...
 	if (m_inp5->read() == 0x01) // ...PRESENT?
 	{
@@ -1119,7 +1177,7 @@ void rainbow_state::machine_reset()
 				output().set_value("led1", 1);
 
 				uint32_t max_sector = (info->cylinders) * (info->heads) * (info->sectors);
-				printf("\n%u (%3.2f) MB HARD DISK MOUNTED. GEOMETRY: %d HEADS (1..%d ARE OK).\n%d CYLINDERS (151 to %d ARE OK).\n%d SECTORS / TRACK (up to %d ARE OK). \n%d BYTES / SECTOR (128 to 1024 ARE OK).\n",
+				popmessage("\n%u (%3.2f) MB HARD DISK MOUNTED. GEOMETRY: %d HEADS (1..%d ARE OK).\n%d CYLINDERS (151 to %d ARE OK).\n%d SECTORS / TRACK (up to %d ARE OK). \n%d BYTES / SECTOR (128 to 1024 ARE OK).\n",
 					max_sector * info->sectorbytes / 1000000,
 					(float)max_sector * (float)info->sectorbytes / 1048576.0f,
 					info->heads, RD51_MAX_HEAD,
@@ -1137,8 +1195,13 @@ void rainbow_state::machine_reset()
 	m_fdc->dden_w(0);
 
 	// *********** NEC 7220 DISPLAY CONTROLLER [ OPTIONAL ]
-	GDC_RESET_MACRO
+	OPTION_GRFX_RESET
+
+	OPTION_RESET_PATTERNS
 
+	for(int i=0; i <32; i++) { m_GDC_COLOR_MAP[i] = 0x00; };
+	m_GDC_color_map_index = 0;
+	m_color_map_changed = true;
 	// *********** Z80
 
 	m_z80->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
@@ -1176,9 +1239,6 @@ void rainbow_state::machine_reset()
 	output().set_value("led_compose", 0); // led9
 	output().set_value("led_lock", 0);    // led10
 	output().set_value("led_hold", 0);    // led11
-
-	if (m_POWER_GOOD) // When user presses F3, a hard reset is executed.
-		machine().schedule_hard_reset(); // better ask via GUI? How...?
 }
 
 // Simulate AC_OK signal (power good) and RESET after ~ 108 ms.
@@ -1207,15 +1267,6 @@ uint32_t rainbow_state::screen_update_rainbow(screen_device &screen, bitmap_ind1
 {
 	static int old_palette, old_monitor;
 
-#ifdef BOOST_DEBUG_PERFORMANCE
-	uint8_t *ram = memregion("maincpu")->base();
-	if( !(m_p_vol_ram[0x84] == 0x00) )
-	{
-		if( (MOTOR_DISABLE_counter) || (ram[0xEFFFE] & 16) ) // if HDD/FDD ACTIVITY -OR- SMOOTH SCROLL IN PROGRESS
-			return 0;
-	}
-#endif
-
 	int monitor_selected = m_inp13->read();
 	if(monitor_selected != old_monitor)
 	{
@@ -1235,6 +1286,15 @@ uint32_t rainbow_state::screen_update_rainbow(screen_device &screen, bitmap_ind1
 		m_color_map_changed = true;
 	}
 
+#ifdef BOOST_DEBUG_PERFORMANCE
+	uint8_t *ram = memregion("maincpu")->base();
+	if( !(m_p_vol_ram[0x84] == 0x00) )
+	{
+		if( (MOTOR_DISABLE_counter) || (ram[0xEFFFE] & 16) ) // if HDD/FDD ACTIVITY -OR- SMOOTH SCROLL IN PROGRESS
+			return 0;
+	}
+#endif
+
 	m_crtc->palette_select(palette_selected);
 
 	if(    m_SCREEN_BLANK                    ||
@@ -1270,7 +1330,6 @@ void rainbow_state::update_8088_irqs()
 void rainbow_state::raise_8088_irq(int ref)
 {
 	m_irq_mask |= (1 << ref);
-
 	update_8088_irqs();
 }
 
@@ -1284,12 +1343,10 @@ void rainbow_state::lower_8088_irq(int ref)
 // IRQ service for 7201 (commm / printer)
 void rainbow_state::update_mpsc_irq()
 {
-	if (m_mpsc_irq == 0) {
+	if (m_mpsc_irq == 0)
 		lower_8088_irq(IRQ_COMM_PTR_INTR_L);
-		m_mpsc->m1_r();  // interrupt acknowledge
-	} else
+	else
 		raise_8088_irq(IRQ_COMM_PTR_INTR_L);
-
 }
 
 WRITE_LINE_MEMBER(rainbow_state::mpsc_irq)
@@ -1298,25 +1355,27 @@ WRITE_LINE_MEMBER(rainbow_state::mpsc_irq)
 	update_mpsc_irq();
 }
 
-// PORT 0x0e : Printer bit rates
-WRITE8_MEMBER(rainbow_state::printer_bitrate_w)
-{
-	printf("\nPRINTER bitrate = %02x HEX\n",data & 7);
-
-	// "bit 3 controls the communications port clock (RxC,TxC). External clock when 1, internal when 0"
-	printf(" - CLOCK BIT: %02x", data & 8);
-}
-
 // PORT 0x06 : Communication bit rates (see page 21 of PC 100 SPEC)
 WRITE8_MEMBER(rainbow_state::comm_bitrate_w)
 {
-	m_dbrg->str_w(data & 0x0f);  // PDF is wrong, low nibble is RECEIVE clock (verified in SETUP).
+	m_dbrg_A->str_w(data & 0x0f);  // PDF is wrong, low nibble is RECEIVE clock (verified in SETUP).
 	printf("\nRECEIVE bitrate = %02x HEX\n",data & 0x0f);
 
-	m_dbrg->stt_w( ((data & 0xf0) >> 4) );
+	m_dbrg_A->stt_w( ((data & 0xf0) >> 4) );
 	printf("\nTRANSMIT bitrate = %02x HEX\n",(data & 0xf0) >> 4);
 }
 
+// PORT 0x0e : Printer bit rates
+WRITE8_MEMBER(rainbow_state::printer_bitrate_w)
+{
+	m_dbrg_B->str_w(data & 7); // bits 0 - 2
+	m_dbrg_B->stt_w(data & 7); // TX and RX rate cannot be programmed independently.
+	printf("\n(PRINTER) RECEIVE / TRANSMIT bitrate = %02x HEX\n",data & 7);
+
+	// "bit 3 controls the communications port clock (RxC,TxC). External clock when 1, internal when 0"
+	printf(" - CLOCK (0 = internal): %02x", data & 8);
+}
+
 WRITE_LINE_MEMBER(rainbow_state::com8116_a_fr_w)
 {
 	m_mpsc->rxca_w(state);
@@ -1327,6 +1386,15 @@ WRITE_LINE_MEMBER(rainbow_state::com8116_a_ft_w)
 	m_mpsc->txca_w(state);
 }
 
+WRITE_LINE_MEMBER(rainbow_state::com8116_b_fr_w)
+{
+	m_mpsc->rxcb_w(state);
+}
+
+WRITE_LINE_MEMBER(rainbow_state::com8116_b_ft_w)
+{
+	m_mpsc->txcb_w(state);
+}
 
 // Only Z80 * private SRAM * is wait state free
 // (= fast enough to allow proper I/O to the floppy)
@@ -1386,22 +1454,63 @@ WRITE8_MEMBER(rainbow_state::share_z80_w)
 	return;
 }
 
+// NMI logic (parity test)
+WRITE8_MEMBER(rainbow_state::ext_ram_w)
+{
+	m_ext_ram[offset] = data;
 
-// ------------------------ClikClok (for model B; DS1315)  ---------------------------------
-// DESCRIPTION: version for 100-A plugs into NVRAM chip socket (unemulated yet)
-//   On a 100-B, it occupies one of the EPROM sockets. There is a socket on the ClikClok for the NVRAM / EPROM.
+#ifndef OLD_RAM_BOARD_PRESENT
+	if(m_diagnostic & 0x08)
+		if( (offset + 0x10000) >= (MOTHERBOARD_RAM + 1))
+			m_i8088->set_input_line(INPUT_LINE_NMI, PULSE_LINE);
+#endif
+}
 
-// DRIVERS: (a) DOS and CP/M binaries plus source from DEC employee (rbclik); Reads & displays times. Y2K READY!
-// (b) Suitable Solutions ClikClok distribution disk; Uses $FE000 and up. 2 digit year. Needed to set time & date.
-//
-// TODO: obtain hardware / check address decoders.
-// RTC accesses here were derived from Vincent Esser's published source.
+// ------------------------ClikClok (for 100-A; DS1315) ------------------------------------------
+// Version for 100-A plugs into NVRAM chip socket. There is a socket on the ClikClok for the NVRAM
+
+// Requires a short program from the Suitable Solutions ClikClok distribution disk (CLIKA.COM)
+// - also needed to set time/date (*).                   Reads $ed000, writes ed0fe/ed0ff.
+WRITE8_MEMBER(rainbow_state::rtc_w)
+{
+	if((m_inp11->read() == 0x01)) // if enabled...
+	{
+		switch (offset)
+		{
+			case 0x00: // Write to 0xED0FE
+				if (m_rtc->chip_enable())
+					m_rtc->write_data(space, offset & 0x01); // Transfer data to DS1315 (data = offset):
+				else
+					m_rtc->read_0(space, 0); // (RTC ACTIVATION) read magic pattern 0
+				break;
+
+			case 0x01: // Write to 0xED0FF
+				if (m_rtc->chip_enable())
+					m_rtc->write_data(space, offset & 0x01); // Transfer data to DS1315 (data = offset):
+				else
+					m_rtc->read_1(space, 0); // (RTC ACTIVATION) read magic pattern 1
+				break;
+		}
+	}
+	m_p_vol_ram[offset] = data;  // Poke value into VOL_RAM.
+}
+
+// ------------------------ClikClok (for 100-B; DS1315)  ------------------------------------------------
+// Add-on hardware, occupies one of the EPROM sockets of the 100-B. TODO: check address decoders on board
+// Requires CLIKCLOK.COM or RBCLIK21.COM (freeware from Latrobe).                       Uses FC000/FE000.
 READ8_MEMBER(rainbow_state::rtc_r)
 {
 	if((m_inp11->read() == 0x01)) // if enabled...
 	{
 		switch (offset)
 		{
+#ifdef ASSUME_RAINBOW_A_HARDWARE
+			case 0x00: // read time/date from 0xED000 (ClikClok for 100-A)
+				if (m_rtc->chip_enable())
+					return m_rtc->read_data(space, 0) & 0x01;
+				 else
+					m_rtc->chip_reset();
+#else
 			// Transfer data to DS1315 (data = offset):
 			case 0x0000:  // RTC_WRITE_DATA_0 0xFC000
 			case 0x2000:  // RTC_WRITE_DATA_0 0xFE000 (MIRROR)
@@ -1417,13 +1526,13 @@ READ8_MEMBER(rainbow_state::rtc_r)
 				if (m_rtc->chip_enable())
 					return (m_rtc->read_data(space, 0) & 0x01);
 
-			// (RTC ACTIVATION) READ MAGIC PATTERN 0
+			// (RTC ACTIVATION) read magic pattern 0
 			case 0x0100:  // 0xFC100
 			case 0x2100:  // 0xFE100 (MIRROR)
 				m_rtc->read_0(space, 0);
 				break;
 
-			// (RTC ACTIVATION) READ MAGIC PATTERN 1
+			// (RTC ACTIVATION) read magic pattern 1
 			case 0x0101:  // 0xFC101
 			case 0x2101:  // 0xFE101 (MIRROR)
 				m_rtc->read_1(space, 0);
@@ -1434,11 +1543,16 @@ READ8_MEMBER(rainbow_state::rtc_r)
 			case 0x2104:  // 0xFE104 (MIRROR)
 				m_rtc->chip_reset();
 				break;
+#endif
 		}
 	}
 
+#ifdef ASSUME_RAINBOW_A_HARDWARE
+	return m_p_vol_ram[offset];  // return volatile RAM
+#else
 	uint8_t *rom = memregion("maincpu")->base();
-	return rom[RTC_BASE + offset];  // Return ROM to prevent crashes
+	return rom[RTC_BASE + offset];  // return ROM
+#endif
 }
 // ------------------------/ ClikClok (for model B; DS1315)  ---------------------------------
 
@@ -1500,18 +1614,15 @@ hard_disk_file *(rainbow_state::rainbow_hdc_file(int drv))
 	}
 	else
 	{
-		printf("\n <<< === REJECTED = (SANITY CHECK FAILED) === >>> \n");
-
 		uint32_t max_sector = info->cylinders * info->heads * info->sectors;
-				printf("\n%u (%3.2f) MB HARD DISK REJECTED. GEOMETRY: %d HEADS (1..%d ARE OK).\n%d CYLINDERS (151 to %d ARE OK).\n%d SECTORS / TRACK (up to %d ARE OK). \n%d BYTES / SECTOR (128 to 1024 ARE OK).\n",
+		popmessage("\n%u (%3.2f) MB HARD DISK REJECTED. GEOMETRY: %d HEADS (1..%d ARE OK).\n%d CYLINDERS (151 to %d ARE OK).\n%d SECTORS / TRACK (up to %d ARE OK). \n%d BYTES / SECTOR (128 to 1024 ARE OK).\n",
 					max_sector * info->sectorbytes / 1000000,
 					(float)max_sector * (float)info->sectorbytes / 1048576.0f,
 					info->heads, RD51_MAX_HEAD,
 					info->cylinders, RD51_MAX_CYLINDER,
 					info->sectors, RD51_SECTORS_PER_TRACK,
 					info->sectorbytes);
-
-		printf("\n <<< === REJECTED = (SANITY CHECK FAILED) === >>> \n");
+		printf("\n <<< === HARD DISK IMAGE REJECTED = (invalid geometry) === >>> \n");
 		return nullptr;
 	}
 }
@@ -2126,7 +2237,7 @@ READ8_MEMBER(rainbow_state::z80_generalstat_r)
 	int fdc_write_gate = 0;
 	int last_dir = 0;
 
-	printf("\nFLOPPY %02d - ", m_unit);
+//  printf("\nFLOPPY %02d - ", m_unit);
 	if (m_fdc)
 	{
 			track = m_fdc->track_r(space, 0);
@@ -2349,6 +2460,9 @@ IRQ_CALLBACK_MEMBER(rainbow_state::irq_callback)
 				if (i == IRQ_8088_VBL)  // If VBL IRQ acknowledged...
 					m_crtc->MHFU(MHFU_RESET); // ...reset counter (also: DC012_W)
 
+				if (i == IRQ_COMM_PTR_INTR_L)
+					m_mpsc->m1_r();  // serial interrupt acknowledge
+
 				intnum = vectors[i] | m_irq_high;
 				break;
 			}
@@ -2364,18 +2478,12 @@ WRITE_LINE_MEMBER(rainbow_state::GDC_vblank_irq)
 	// VERIFICATION NEEDED: IRQ raised before or after new palette loaded...?
 	if(m_GDC_MODE_REGISTER & GDC_MODE_ENABLE_VSYNC_IRQ) // 0x40
 		raise_8088_irq(IRQ_GRF_INTR_L);
+	else
+		lower_8088_irq(IRQ_GRF_INTR_L);
 
 	uint8_t red, green, blue, mono;
 	int xi;
 
-	if(m_scroll_buffer_changed)
-	{
-		m_scroll_buffer_changed = false;
-
-		for(xi = 0; xi < m_GDC_scroll_index; xi++) // LOAD REAL SCROLL BUFFER FROM PRELOAD (up to scroll_index...?)
-				m_GDC_SCROLL_BUFFER[xi] = m_GDC_SCROLL_BUFFER_PRELOAD[xi];
-	}
-
 	if(m_color_map_changed)
 	{
 		m_color_map_changed = false;
@@ -2432,6 +2540,9 @@ WRITE_LINE_MEMBER(rainbow_state::GDC_vblank_irq)
 							}
 
 							case COLOR_MONITOR:
+
+									if(!(m_GDC_MODE_REGISTER & GDC_MODE_ENABLE_VIDEO))
+										red = blue = 0; // Page 21 of PDF AA-AE36A (PDF) explains why
 									red   = uint8_t( red   * 17 *  ( (255-video_levels[ red ]  )  / 255.0f) );
 									green = uint8_t( mono * 17 *  ( (255-video_levels[ mono ])  / 255.0f) ); // BCC-17 cable (red, mono -> green, blue)
 									blue  = uint8_t( blue  * 17 *  ( (255-video_levels[ blue ] )  / 255.0f) );
@@ -2456,6 +2567,7 @@ WRITE_LINE_MEMBER(rainbow_state::GDC_vblank_irq)
 			 if ( m_inp13->read() == DUAL_MONITOR)
 				printf(" [HINT: DUAL MONITOR (DIP SWITCH) WRONG! NO GREEN PALETTE] ");
 	} // color map changed?
+
 } // 7220 vblank IRQ
 
 
@@ -2466,10 +2578,10 @@ INTERRUPT_GEN_MEMBER(rainbow_state::vblank_irq)
 
 	if (m_POWER_GOOD && m_crtc->MHFU(MHFU_IS_ENABLED)) // If enabled...
 	{
-		if (m_crtc->MHFU(MHFU_VALUE) > 7) // + more than (7 * 16.666) msecs gone (108 ms would be by the book)
+		if (m_crtc->MHFU(MHFU_VALUE) > 10) // + more than (10 * 16.666) msecs gone (108 ms would be by the book)
 		{
 			m_crtc->MHFU(MHFU_RESET_and_DISABLE);
-			printf("\n**** WATCHDOG TRIPPED:nVBL IRQ not acknowledged within (at least) 108 milliseconds. ****\n");
+			popmessage("\n**** WATCHDOG TRIPPED:nVBL IRQ not acknowledged within (at least) 108 milliseconds. ****\n");
 
 			if (m_inp12->read() == 0x01) // (DIP) for watchdog active?
 				cmd_timer->adjust(attotime::from_msec(RESET_DURATION_MS));
@@ -2542,13 +2654,9 @@ WRITE8_MEMBER(rainbow_state::diagnostic_w) // 8088 (port 0A WRITTEN). Fig.4-28 +
 			printf("DATA: %x (PC=%x)\n", data, machine().device("maincpu")->safe_pc());
 	}
 
-	// BIT 3: PARITY TEST (1 = enables parity test on memory option board).
+	// BIT 3: PARITY (1 enables parity test on memory board. Usually 64K per bank). -> ext_ram_w.
 	if(data & 0x08)
-	{
-		printf("\n*** UNEMULATED PARITY TEST [on RAM EXTENSION] - (bit 3 in diagnostic_w) ");
-		//   FIXME: parity test = NMI? When should NMI fire? Per RAM bank?
-		//   m_i8088->set_input_line_and_vector(INPUT_LINE_NMI, ASSERT_LINE, 0x02);
-	}
+		printf("\n*** PARITY TEST [on RAM EXTENSION] - (bit 3 - diagnostic_w) ");
 
 	// MISSING BITS (* not vital for normal operation, see diag.disk) -
 	// * BIT 4: DIAG LOOPBACK (0 at power-up; 1 directs RX50 and DC12 output to printer port)
@@ -2703,36 +2811,32 @@ READ16_MEMBER(rainbow_state::vram_r)
 // NOTE: Rainbow has separate registers for fore and background.
 WRITE16_MEMBER(rainbow_state::vram_w)
 {
-	if(!(m_GDC_MODE_REGISTER & GDC_MODE_VECTOR))
-	{
-		// SCROLL_MAP IN BITMAP MODE ONLY...?
-		if(m_GDC_MODE_REGISTER & GDC_MODE_HIGHRES)
-			offset = ( m_GDC_SCROLL_BUFFER[ (offset & 0x3FC0) >> 6 ] << 6) |  (offset & 0x3F);
-		else
-			offset = ( m_GDC_SCROLL_BUFFER[ (offset & 0x1FC0) >> 6 ] << 6) |  (offset & 0x3F);
-	}
+	if(m_GDC_MODE_REGISTER & GDC_MODE_HIGHRES)
+		offset = ( m_GDC_SCROLL_BUFFER[ (offset & 0x3FC0) >> 6 ] << 6) |  (offset & 0x3F);
+	else
+		offset = ( m_GDC_SCROLL_BUFFER[ (offset & 0x1FC0) >> 6 ] << 6) |  (offset & 0x3F);
 
 	offset &= 0xffff; // same as in VT240?
 	uint16_t chr = data; // VT240 : uint8_t
 
 	if(m_GDC_MODE_REGISTER & GDC_MODE_VECTOR) // VT240 : if(SELECT_VECTOR_PATTERN_REGISTER)
 	{
-			chr = BITSWAP8(m_vpat, m_patidx, m_patidx, m_patidx, m_patidx, m_patidx, m_patidx, m_patidx, m_patidx);
-			chr |= (chr << 8);
-			if(m_patcnt-- == 0)
-			{
-				m_patcnt = m_patmult;
-				if(m_patidx-- == 0)
-					m_patidx = 7;
-			}
+		chr = BITSWAP8(m_vpat, m_patidx, m_patidx, m_patidx, m_patidx, m_patidx, m_patidx, m_patidx, m_patidx);
+		chr |= (chr << 8);
+		if(m_patcnt-- == 0)
+		{
+			m_patcnt = m_patmult;
+			if(m_patidx-- == 0)
+				m_patidx = 7;
+		}
 	}
-		else
+	else
 	{
-			chr = m_GDC_WRITE_BUFFER[ m_GDC_write_buffer_index++ ];
-			m_GDC_write_buffer_index &= 0xf;
+		chr = m_GDC_WRITE_BUFFER[ m_GDC_write_buffer_index++ ];
+		m_GDC_write_buffer_index &= 0xf;
 
-			chr |= (m_GDC_WRITE_BUFFER[m_GDC_write_buffer_index++] << 8);
-			m_GDC_write_buffer_index &= 0xf;
+		chr |= (m_GDC_WRITE_BUFFER[m_GDC_write_buffer_index++] << 8);
+		m_GDC_write_buffer_index &= 0xf;
 	}
 
 	if(m_GDC_MODE_REGISTER & GDC_MODE_ENABLE_WRITES) // 0x10
@@ -2767,10 +2871,10 @@ WRITE16_MEMBER(rainbow_state::vram_w)
 						break;
 				}
 
-				if(!(m_GDC_MODE_REGISTER & GDC_MODE_VECTOR)) // 0 : (NOT VECTOR MODE) Text Mode and Write Mask Batch
+				if(!(m_GDC_MODE_REGISTER & GDC_MODE_VECTOR)) // 0 : Text Mode and Write Mask Batch
 					out = (out & ~m_GDC_WRITE_MASK) | (mem & m_GDC_WRITE_MASK); // // M_MASK (1st use)
 				else
-					out = (out & ~data) | (mem & data); // VECTOR MODE !
+					out = (out & ~data) | (mem & data); // vector mode
 
 				if(m_GDC_MODE_REGISTER & GDC_MODE_ENABLE_WRITES) // 0x10
 					m_video_ram[(offset & 0xffff) + (0x8000 * i)] = out;
@@ -2785,7 +2889,7 @@ WRITE16_MEMBER(rainbow_state::vram_w)
 }
 
 // (READ)
-// Read _preloaded_ scroll buffer (see GDC Diagnostic Disk, SCROLL BUFFER test)
+// Read  scroll buffer (see GDC Diagnostic Disk, SCROLL BUFFER test)
 READ8_MEMBER(rainbow_state::GDC_EXTRA_REGISTER_r)
 {
 	uint8_t out = 0;
@@ -2799,7 +2903,7 @@ READ8_MEMBER(rainbow_state::GDC_EXTRA_REGISTER_r)
 			if(m_GDC_INDIRECT_REGISTER & GDC_SELECT_SCROLL_MAP ) // 0x80
 			{
 				// Documentation says it is always incremented (read and write):
-				out = m_GDC_SCROLL_BUFFER_PRELOAD[m_GDC_scroll_index++]; // // * READ * SCROLL_MAP ( 256 x 8 )
+				out = m_GDC_SCROLL_BUFFER[m_GDC_scroll_index++]; // // * READ * SCROLL_MAP ( 256 x 8 )
 				m_GDC_scroll_index &= 0xFF; // 0...255  (CPU accesses 256 bytes)
 				break;
 			}
@@ -2821,13 +2925,13 @@ WRITE8_MEMBER(rainbow_state::GDC_EXTRA_REGISTER_w)
 	if(offset > 0) // Port $50 reset done @ boot ROM 1EB4/8 regardless if option present.
 		if (m_inp7->read() != 1)
 		{
-				if(last_message != 1)
-				{
-					printf("\nCOLOR GRAPHICS ADAPTER INVOKED.  PLEASE TURN ON THE APPROPRIATE DIP SWITCH, THEN RESTART.\n");
-					printf("OFFSET: %x (PC=%x)\n", 0x50 +offset , machine().device("maincpu")->safe_pc());
-					last_message = 1;
-				}
-				return;
+			if(last_message != 1)
+			{
+				popmessage("\nCOLOR GRAPHICS ADAPTER INVOKED.  PLEASE TURN ON THE APPROPRIATE DIP SWITCH, THEN REBOOT.\n");
+				printf("OFFSET: %x (PC=%x)\n", 0x50 +offset , machine().device("maincpu")->safe_pc());
+				last_message = 1;
+			}
+			return;
 		}
 
 	switch(offset)
@@ -2835,12 +2939,13 @@ WRITE8_MEMBER(rainbow_state::GDC_EXTRA_REGISTER_w)
 		case 0: // Mode register must be reloaded following any write to port 50 (software reset).
 			// FIXME: "Any write to this port also resynchronizes the
 			//        read/modify/write memory cycles of the Graphics Option to those of the GDC." (?)
-			if( data & 1 ) // PDF QV069 suggests 1 -> 0 -> 1; most programs just set bit 0.
+
+			if( data & 1 ) // PDF QV069 suggests 1 -> 0 -> 1. Most programs just set bit 0 (PACMAN).
 			{
-				GDC_RESET_MACRO // Graphics option software reset (separate from GDC reset...)
-				printf("(PC=%x)\n", machine().device("maincpu")->safe_pc());
+				// Graphics option software reset (separate from GDC reset...)
+				OPTION_GRFX_RESET
+				OPTION_RESET_PATTERNS
 			}
-			m_PORT50  = data;
 			break;
 
 		case 1: //  51h - DATA loaded into register previously written to 53h.
@@ -2878,21 +2983,18 @@ WRITE8_MEMBER(rainbow_state::GDC_EXTRA_REGISTER_w)
 			{
 				if(!( m_GDC_MODE_REGISTER & GDC_MODE_READONLY_SCROLL_MAP)) // ? READONLY / WRITE logic  correct...?
 				{
-					m_GDC_SCROLL_BUFFER_PRELOAD[m_GDC_scroll_index] = data; // // WRITE TO SCROLL_MAP ( 256 x 8 )
+					m_GDC_SCROLL_BUFFER[m_GDC_scroll_index] = data; // // WRITE TO SCROLL_MAP ( 256 x 8 )
 
 					if(m_GDC_scroll_index == 255)
 									printf("\n ---- SCROLL MAP FULLY LOADED ---*");
 					m_GDC_scroll_index++;
 					m_GDC_scroll_index &= 0xFF; // 0...255  (CPU accesses 256 bytes)
-
-					m_scroll_buffer_changed = true;
 				}
 				break;
 			}
 
 			// -----------------PATTERN + MULTIPLIER USED IN VECTOR MODE ONLY!
 			// SEE PAGE 37 OF AA-AE36A (PDF).
-			// NOTE : Pattern Multiplier MUST BE LOADED before loading PATTERN.
 			if(m_GDC_INDIRECT_REGISTER & GDC_SELECT_PATTERN_MULTIPLIER)
 			{
 				// On a Rainbow, 12 indicates a multiplier of 16-12 = 4 (example)
@@ -2902,9 +3004,9 @@ WRITE8_MEMBER(rainbow_state::GDC_EXTRA_REGISTER_w)
 
 			if(m_GDC_INDIRECT_REGISTER & GDC_SELECT_PATTERN)
 			{
+				// NOTE : Pattern Multiplier MUST BE LOADED before (!)
+				OPTION_RESET_PATTERNS
 				m_vpat = data;
-				m_patcnt = m_patmult;
-				m_patidx = 7; // correct...?
 				break;
 			}
 
@@ -3054,10 +3156,7 @@ MCFG_CPU_VBLANK_INT_DRIVER("screen", rainbow_state, vblank_irq)
 
 /* video hardware */
 MCFG_SCREEN_ADD("screen", RASTER)
-MCFG_SCREEN_REFRESH_RATE(60)
-MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */
-MCFG_SCREEN_SIZE(132 * 10, 49 * 10)
-MCFG_SCREEN_VISIBLE_AREA(0, 80 * 10 - 1, 0, 48 * 10 - 1)
+MCFG_SCREEN_RAW_PARAMS(XTAL_24_0734MHz / 6, 442, 0, 400, 264, 0, 240) // ~NTSC compatible video timing (?)
 
 MCFG_SCREEN_UPDATE_DRIVER(rainbow_state, screen_update_rainbow)
 MCFG_SCREEN_PALETTE("vt100_video:palette")
@@ -3071,7 +3170,8 @@ MCFG_VT_VIDEO_RAM_CALLBACK(READ8(rainbow_state, read_video_ram_r))
 MCFG_VT_VIDEO_CLEAR_VIDEO_INTERRUPT_CALLBACK(WRITELINE(rainbow_state, clear_video_interrupt))
 
 // *************************** COLOR GRAPHICS (OPTION) **************************************
-MCFG_DEVICE_ADD("upd7220", UPD7220, 31188000 / 4) // Duell schematics shows a 31.188 Mhz clock (confirmed by RFKA; not in XTAL)
+// While the OSC frequency is confirmed, the divider is not (refresh rate is ~60 Hz with 32).
+MCFG_DEVICE_ADD("upd7220", UPD7220, 31188000 / 32) // Duell schematics shows a 31.188 Mhz oscillator (confirmed by RFKA).
 MCFG_UPD7220_VSYNC_CALLBACK(WRITELINE(rainbow_state, GDC_vblank_irq)) // "The vsync callback line needs to be below the 7220 DEVICE_ADD line."
 
 MCFG_DEVICE_ADDRESS_MAP(AS_0, upd7220_map)
@@ -3081,12 +3181,15 @@ MCFG_PALETTE_ADD("palette2", 32)
 
 MCFG_SCREEN_ADD("screen2", RASTER)
 MCFG_SCREEN_VIDEO_ATTRIBUTES(VIDEO_UPDATE_AFTER_VBLANK | VIDEO_ALWAYS_UPDATE)
-MCFG_SCREEN_REFRESH_RATE(60)
-MCFG_SCREEN_UPDATE_DEVICE("upd7220", upd7220_device, screen_update)
 
-MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) // not accurate
-MCFG_SCREEN_SIZE(800, 256)                   // should be 240
-MCFG_SCREEN_VISIBLE_AREA(0, 800-1, 0, 256-1) // should be 240
+// VR241 color monitor is specified for 20 MHz bandwidth ( 60 Hz / 15.72 kHz horizontal rate )
+// - sufficient for 800 x 240 non-interlaced at 60 Hz (non interlaced).
+//MCFG_SCREEN_RAW_PARAMS(31188000 / 2 , 992, 0, 800, 262, 0, 240)
+
+// Alternate configuration:
+MCFG_SCREEN_RAW_PARAMS(31188000 / 4 , 496, 0, 400, 262, 0, 240)
+
+MCFG_SCREEN_UPDATE_DEVICE("upd7220", upd7220_device, screen_update)
 
 MCFG_FD1793_ADD(FD1793_TAG, XTAL_24_0734MHz / 24) // no separate 1 Mhz quartz
 MCFG_FLOPPY_DRIVE_ADD(FD1793_TAG ":0", rainbow_floppies, "525qd0", rainbow_state::floppy_formats)
@@ -3121,10 +3224,14 @@ MCFG_HARDDISK_ADD("harddisk1")
 
 MCFG_DS1315_ADD("rtc") // DS1315 (ClikClok for DEC-100 B)   * OPTIONAL *
 
-MCFG_DEVICE_ADD("com8116", COM8116, XTAL_5_0688MHz)     // Baud rate generator
+MCFG_DEVICE_ADD("com8116_a", COM8116, XTAL_5_0688MHz)     // Baud rate generator A
 MCFG_COM8116_FR_HANDLER(WRITELINE(rainbow_state, com8116_a_fr_w))
 MCFG_COM8116_FT_HANDLER(WRITELINE(rainbow_state, com8116_a_ft_w))
 
+MCFG_DEVICE_ADD("com8116_b", COM8116, XTAL_5_0688MHz) // Baud rate generator B
+MCFG_COM8116_FR_HANDLER(WRITELINE(rainbow_state, com8116_b_fr_w))
+MCFG_COM8116_FT_HANDLER(WRITELINE(rainbow_state, com8116_b_ft_w))
+
 MCFG_UPD7201_ADD("upd7201", XTAL_2_5MHz, 0, 0, 0, 0)    // 2.5 Mhz from schematics
 MCFG_Z80DART_OUT_INT_CB(WRITELINE(rainbow_state, mpsc_irq))
 
diff --git a/src/mame/drivers/rastan.cpp b/src/mame/drivers/rastan.cpp
index 95a2af1..05dc3ec 100644
--- a/src/mame/drivers/rastan.cpp
+++ b/src/mame/drivers/rastan.cpp
@@ -171,16 +171,16 @@ WRITE8_MEMBER(rastan_state::rastan_bankswitch_w)
 
 WRITE_LINE_MEMBER(rastan_state::rastan_msm5205_vck)
 {
-	if (m_adpcm_data != -1)
-	{
-		m_msm->data_w(m_adpcm_data & 0x0f);
-		m_adpcm_data = -1;
-	}
-	else
+	if (!state)
+		return;
+
+	m_adpcm_ff = !m_adpcm_ff;
+	m_adpcm_sel->select_w(m_adpcm_ff);
+
+	if (m_adpcm_ff)
 	{
-		m_adpcm_data = memregion("adpcm")->base()[m_adpcm_pos];
+		m_adpcm_sel->ba_w(m_adpcm_data[m_adpcm_pos]);
 		m_adpcm_pos = (m_adpcm_pos + 1) & 0xffff;
-		m_msm->data_w(m_adpcm_data >> 4);
 	}
 }
 
@@ -192,6 +192,7 @@ WRITE8_MEMBER(rastan_state::rastan_msm5205_address_w)
 WRITE8_MEMBER(rastan_state::rastan_msm5205_start_w)
 {
 	m_msm->reset_w(0);
+	m_adpcm_ff = false;
 }
 
 WRITE8_MEMBER(rastan_state::rastan_msm5205_stop_w)
@@ -344,7 +345,7 @@ void rastan_state::machine_start()
 	save_item(NAME(m_sprites_flipscreen));
 
 	save_item(NAME(m_adpcm_pos));
-	save_item(NAME(m_adpcm_data));
+	save_item(NAME(m_adpcm_ff));
 }
 
 void rastan_state::machine_reset()
@@ -352,7 +353,7 @@ void rastan_state::machine_reset()
 	m_sprite_ctrl = 0;
 	m_sprites_flipscreen = 0;
 	m_adpcm_pos = 0;
-	m_adpcm_data = -1;
+	m_adpcm_ff = false;
 }
 
 
@@ -405,6 +406,9 @@ static MACHINE_CONFIG_START( rastan, rastan_state )
 	MCFG_MSM5205_PRESCALER_SELECTOR(MSM5205_S48_4B)      /* 8 kHz */
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.60)
 
+	MCFG_DEVICE_ADD("adpcm_sel", LS157, 0)
+	MCFG_74157_OUT_CB(DEVWRITE8("msm", msm5205_device, data_w))
+
 	MCFG_DEVICE_ADD("tc0140syt", TC0140SYT, 0)
 	MCFG_TC0140SYT_MASTER_CPU("maincpu")
 	MCFG_TC0140SYT_SLAVE_CPU("audiocpu")
diff --git a/src/mame/drivers/rbmk.cpp b/src/mame/drivers/rbmk.cpp
index 2fdbe11..59f83c6 100644
--- a/src/mame/drivers/rbmk.cpp
+++ b/src/mame/drivers/rbmk.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina, David Haywood
 /*
 Real Battle Mahjong King by 'Game Men System Co. Ltd.'
diff --git a/src/mame/drivers/rltennis.cpp b/src/mame/drivers/rltennis.cpp
index 3995615..4eb15de 100644
--- a/src/mame/drivers/rltennis.cpp
+++ b/src/mame/drivers/rltennis.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /****************************************************************************************
 Reality Tennis - (c) 1993 TCH
diff --git a/src/mame/drivers/s7.cpp b/src/mame/drivers/s7.cpp
index 3f98199..66a9fb4 100644
--- a/src/mame/drivers/s7.cpp
+++ b/src/mame/drivers/s7.cpp
@@ -880,8 +880,8 @@ GAME( 1982, vrkon_l1, 0,        s7, s7, s7_state, s7, ROT0, "Williams", "Varkon
 GAME( 1982, tmfnt_l5, 0,        s7, s7, s7_state, s7, ROT0, "Williams", "Time Fantasy (L-5)", MACHINE_MECHANICAL | MACHINE_NOT_WORKING )
 GAME( 1982, wrlok_l3, 0,        s7, s7, s7_state, s7, ROT0, "Williams", "Warlok (L-3)", MACHINE_MECHANICAL | MACHINE_NOT_WORKING )
 GAME( 1982, dfndr_l4, 0,        s7, s7, s7_state, s7, ROT0, "Williams", "Defender (L-4)", MACHINE_MECHANICAL | MACHINE_NOT_WORKING )
-GAME( 1983, jst_l2,   0,        s7, s7, s7_state, s7, ROT0, "Williams", "Joust (L-2)", MACHINE_MECHANICAL | MACHINE_NOT_WORKING | MACHINE_NOT_WORKING )
-GAME( 1983, jst_l1,   jst_l2,   s7, s7, s7_state, s7, ROT0, "Williams", "Joust (L-1)", MACHINE_MECHANICAL | MACHINE_NOT_WORKING | MACHINE_NOT_WORKING )
+GAME( 1983, jst_l2,   0,        s7, s7, s7_state, s7, ROT0, "Williams", "Joust (L-2)", MACHINE_MECHANICAL | MACHINE_NOT_WORKING )
+GAME( 1983, jst_l1,   jst_l2,   s7, s7, s7_state, s7, ROT0, "Williams", "Joust (L-1)", MACHINE_MECHANICAL | MACHINE_NOT_WORKING )
 GAME( 1983, lsrcu_l2, 0,        s7, s7, s7_state, s7, ROT0, "Williams", "Laser Cue (L-2)", MACHINE_MECHANICAL | MACHINE_NOT_WORKING )
 GAME( 1983, fpwr2_l2, 0,        s7, s7, s7_state, s7, ROT0, "Williams", "Firepower II (L-2)", MACHINE_MECHANICAL | MACHINE_NOT_WORKING )
 GAME( 1984, strlt_l1, 0,        s7, s7, s7_state, s7, ROT0, "Williams", "Star Light (L-1)", MACHINE_MECHANICAL | MACHINE_NOT_WORKING )
diff --git a/src/mame/drivers/savquest.cpp b/src/mame/drivers/savquest.cpp
index 69f4a5d..3d20a6f 100644
--- a/src/mame/drivers/savquest.cpp
+++ b/src/mame/drivers/savquest.cpp
@@ -8,7 +8,12 @@
     Skeleton by R. Belmont
 
     TODO:
-    - currently asserts by selecting a s3 video bank above 1M (register 0x6a)
+    - currently asserts by selecting a s3 video bank above 1M (register 0x6a)z
+
+    - The version is labeled "SQ05" in the filesystem but has the 1999 release year.
+      Other components are labeled "v0.5", but the game doesn't boot far enough to see if
+      any graphics have version information. There appears to also be a "Savage Quest 2.1" which
+      is undumped.
 
     PCI list:
     Bus no. Device No. Func No. Vendor ID Device ID Device Class          IRQ
diff --git a/src/mame/drivers/segag80r.cpp b/src/mame/drivers/segag80r.cpp
index f278a77..d374bc6 100644
--- a/src/mame/drivers/segag80r.cpp
+++ b/src/mame/drivers/segag80r.cpp
@@ -172,8 +172,8 @@ offs_t segag80r_state::decrypt_offset(address_space &space, offs_t offset)
 	if ((uint16_t)pc == 0xffff || space.read_byte(pc) != 0x32)
 		return offset;
 
-	/* fetch the low byte of the address and munge it */
-	return (offset & 0xff00) | (*m_decrypt)(pc, space.read_byte(pc + 1));
+	/* munge the low byte of the address */
+	return (offset & 0xff00) | (*m_decrypt)(pc, offset & 0xff);
 }
 
 WRITE8_MEMBER(segag80r_state::mainram_w)
diff --git a/src/mame/drivers/segas16b.cpp b/src/mame/drivers/segas16b.cpp
index cac9f52..391d399 100644
--- a/src/mame/drivers/segas16b.cpp
+++ b/src/mame/drivers/segas16b.cpp
@@ -1380,10 +1380,6 @@ void segas16b_state::altbeas5_i8751_sim()
 	altbeast_common_i8751_sim(0x3098/2, 0x3096/2, 1);
 }
 
-void segas16b_state::altbeast_i8751_sim()
-{
-	altbeast_common_i8751_sim(0x30c4/2, 0x30c2/2, 0);
-}
 
 
 //-------------------------------------------------
@@ -1893,10 +1889,18 @@ ADDRESS_MAP_END
 //  I8751 MCU ADDRESS MAPS
 //**************************************************************************
 
+WRITE8_MEMBER(segas16b_state::spin_68k_w)
+{
+	// this is probably a hack but otherwise the 68k and i8751 end up fighting
+	// on 'goldnaxe' causing hangs in various places.  maybe the interrupts
+	// should happen at different times, or there's some way to steal the bus?
+	m_maincpu->spin_until_time(m_maincpu->cycles_to_attotime(20000));
+}
+
 static ADDRESS_MAP_START( mcu_io_map, AS_IO, 8, segas16b_state )
 	ADDRESS_MAP_UNMAP_HIGH
 	AM_RANGE(0x0000, 0x001f) AM_MIRROR(0xff00) AM_DEVREADWRITE("mapper", sega_315_5195_mapper_device, read, write)
-	AM_RANGE(MCS51_PORT_P1, MCS51_PORT_P1) AM_READ_PORT("SERVICE")
+	AM_RANGE(MCS51_PORT_P1, MCS51_PORT_P1) AM_READ_PORT("SERVICE") AM_WRITE(spin_68k_w)
 ADDRESS_MAP_END
 
 
@@ -3986,7 +3990,7 @@ ROM_START( aliensyn7 )
 	ROM_LOAD( "epr-10725.a9",  0x20000, 0x8000, CRC(6a50e08f) SHA1(d34b2ccadb8b07d5ad99cab5c5b5b79642c65574) )
 	ROM_LOAD( "epr-10726.a10", 0x30000, 0x8000, CRC(d50b7736) SHA1(b1f8e3b0cf2ffee5382098100cfabe21b383cd51) )
 
-	ROM_REGION( 0x2000, "mcu", 0 ) // MC8123 key
+	ROM_REGION( 0x2000, "mc8123", 0 ) // MC8123 key
 	ROM_LOAD( "317-00xx.key",  0x0000, 0x2000, CRC(76b370cd) SHA1(996a4a24dec085caf93cbe614d3b0888379c91dd) )
 ROM_END
 
@@ -4068,7 +4072,7 @@ ROM_START( altbeast )
 	ROM_LOAD( "opr-11673.a12", 0x30000, 0x20000, CRC(400c4a36) SHA1(de4bdfa91734410e0a7f6a16bf8336db172f458a) )
 
 	ROM_REGION( 0x1000, "mcu", 0 )  // Intel i8751 protection MCU
-	ROM_LOAD( "317-0078.c2", 0x00000, 0x1000, NO_DUMP )
+	ROM_LOAD( "317-0078.c2", 0x00000, 0x1000, CRC(8101925f) SHA1(a45d772ebe2fd1a577a6ccac8c6c76bb622258bb) )
 ROM_END
 
 //*************************************************************************************************************************
@@ -4278,7 +4282,7 @@ ROM_START( altbeast4 )
 	ROM_LOAD( "opr-11672.a11", 0x10000, 0x20000, CRC(bbd7f460) SHA1(bbc5c2219cb3a827d84062b19affd9780da2a3cf) )
 	ROM_LOAD( "opr-11673.a12", 0x30000, 0x20000, CRC(400c4a36) SHA1(de4bdfa91734410e0a7f6a16bf8336db172f458a) )
 
-	ROM_REGION( 0x2000, "mcu", 0 ) // MC8123 key
+	ROM_REGION( 0x2000, "mc8123", 0 ) // MC8123 key
 	ROM_LOAD( "317-0066.key",  0x0000, 0x2000, CRC(ed85a054) SHA1(dcc84ec077a8a489f45abfd2bf4a9ba377da28a5) )
 ROM_END
 
@@ -4394,7 +4398,7 @@ ROM_START( altbeast2 )
 	ROM_LOAD( "opr-11672.a11", 0x10000, 0x20000, CRC(bbd7f460) SHA1(bbc5c2219cb3a827d84062b19affd9780da2a3cf) )
 	ROM_LOAD( "opr-11673.a12", 0x30000, 0x20000, CRC(400c4a36) SHA1(de4bdfa91734410e0a7f6a16bf8336db172f458a) )
 
-	ROM_REGION( 0x2000, "mcu", 0 ) // MC8123 key
+	ROM_REGION( 0x2000, "mc8123", 0 ) // MC8123 key
 	ROM_LOAD( "317-0066.key",  0x0000, 0x2000, CRC(ed85a054) SHA1(dcc84ec077a8a489f45abfd2bf4a9ba377da28a5) )
 ROM_END
 
@@ -6197,7 +6201,7 @@ ROM_START( goldnaxe )
 	ROM_LOAD( "mpr-12384.ic6", 0x10000, 0x20000, CRC(6218d8e7) SHA1(5a745c750efb4a61716f99befb7ed14cc84e9973) )
 
 	ROM_REGION( 0x1000, "mcu", 0 )  // Intel i8751 protection MCU
-	ROM_LOAD( "317-0123a.c2", 0x00000, 0x1000, NO_DUMP )
+	ROM_LOAD( "317-0123a.c2", 0x00000, 0x1000, CRC(cf19e7d4) SHA1(51356ae7f278c04aed6dfe4572e8a32a82859d71) )
 ROM_END
 
 //*************************************************************************************************************************
@@ -6448,7 +6452,15 @@ ROM_START( goldnaxe2 )
 	ROM_LOAD( "mpr-12384.a11", 0x10000, 0x20000, CRC(6218d8e7) SHA1(5a745c750efb4a61716f99befb7ed14cc84e9973) )
 
 	ROM_REGION( 0x1000, "mcu", 0 )  // Intel i8751 protection MCU
-	ROM_LOAD( "317-0112.c2", 0x00000, 0x1000, NO_DUMP )
+	/* NOT CURRENTLY USED
+
+	   this chip was faulty, the internal checksum routine fails.  actual code looks like it should be 99.99% the
+	   same as the 'goldnaxe' set but unused areas have different garbage fill data, so finding the bad bits is
+	   difficult.
+
+	   Calculated checksum: 5F8F
+      File checksum:       5E8F */
+	ROM_LOAD( "317-0112.c2", 0x00000, 0x1000, BAD_DUMP CRC(d8f2f1c0) SHA1(04594ed5558af63cde62de6cc4020b35b8a5889e) )
 ROM_END
 
 //*************************************************************************************************************************
@@ -7046,7 +7058,7 @@ ROM_START( cencourt )
 	ROM_LOAD( "epr-a-10.a10", 0x30000, 0x08000, CRC(10263746) SHA1(1f981fb185c6a9795208ecdcfba36cf892a99ed5) ) // == epr-11860.a10
 	ROM_LOAD( "epr-a-11.a11", 0x40000, 0x08000, CRC(38b54a71) SHA1(68ec4ef5b115844214ff2213be1ce6678904fbd2) ) // == epr-11861.a11
 
-	ROM_REGION( 0x2000, "mcu", 0 ) // MC8123 key
+	ROM_REGION( 0x2000, "mc8123", 0 ) // MC8123 key
 	ROM_LOAD( "mc-8123b_center_court.key",  0x0000, 0x2000, CRC(2be5c90b) SHA1(e98d989237f2b001950b876efdb21c1507162830) ) // No official 317-xxxx number
 ROM_END
 
@@ -7478,7 +7490,7 @@ ROM_START( shinobi4 )
 	ROM_LOAD( "epr-11377.a10", 0x00000, 0x08000, CRC(0fb6af34) SHA1(ae9da18bd2db317ed96c5f642f90cc1eba60ba99) ) // MC8123B (317-0054) encrypted version of epr-11361.a10 above
 	ROM_LOAD( "epr-11362.a11", 0x10000, 0x20000, CRC(256af749) SHA1(041bd007ea7708c6d69f07865828b9bd17a139f5) )
 
-	ROM_REGION( 0x2000, "mcu", 0 ) // MC8123 key
+	ROM_REGION( 0x2000, "mc8123", 0 ) // MC8123 key
 	ROM_LOAD( "317-0054.key",  0x0000, 0x2000, CRC(39fd4535) SHA1(93bbb139d2d5acc6a1e338d92077e79a5e880b2e) )
 ROM_END
 
@@ -7516,7 +7528,7 @@ ROM_START( shinobi3 )
 	ROM_LOAD( "epr-11288.a8", 0x10000, 0x8000, CRC(c8df8460) SHA1(0aeb41a493df155edb5f600f53ec43b798927dff) )
 	ROM_LOAD( "epr-11289.a9", 0x20000, 0x8000, CRC(e5a4cf30) SHA1(d1982da7a550c11ab2253f5d64ac6ab847da0a04) )
 
-	ROM_REGION( 0x2000, "mcu", 0 ) // MC8123 key
+	ROM_REGION( 0x2000, "mc8123", 0 ) // MC8123 key
 	ROM_LOAD( "317-0054.key",  0x0000, 0x2000, CRC(39fd4535) SHA1(93bbb139d2d5acc6a1e338d92077e79a5e880b2e) )
 ROM_END
 
@@ -8622,14 +8634,9 @@ DRIVER_INIT_MEMBER(segas16b_state,aceattac_5358)
 DRIVER_INIT_MEMBER(segas16b_state,aliensyn7_5358_small)
 {
 	DRIVER_INIT_CALL(generic_5358_small);
-	mc8123_decode(memregion("soundcpu")->base(), m_sound_decrypted_opcodes, memregion("mcu")->base(), 0x8000);
+	mc8123_decode(memregion("soundcpu")->base(), m_sound_decrypted_opcodes, memregion("mc8123")->base(), 0x8000);
 }
 
-DRIVER_INIT_MEMBER(segas16b_state,altbeast_5521)
-{
-	DRIVER_INIT_CALL(generic_5521);
-	m_i8751_vblank_hook = i8751_sim_delegate(&segas16b_state::altbeast_i8751_sim, this);
-}
 
 DRIVER_INIT_MEMBER(segas16b_state,altbeasj_5521)
 {
@@ -8646,7 +8653,7 @@ DRIVER_INIT_MEMBER(segas16b_state,altbeas5_5521)
 DRIVER_INIT_MEMBER(segas16b_state,altbeas4_5521)
 {
 	DRIVER_INIT_CALL(generic_5521);
-	mc8123_decode(memregion("soundcpu")->base(), m_sound_decrypted_opcodes, memregion("mcu")->base(), 0x8000);
+	mc8123_decode(memregion("soundcpu")->base(), m_sound_decrypted_opcodes, memregion("mc8123")->base(), 0x8000);
 }
 
 DRIVER_INIT_MEMBER(segas16b_state,ddux_5704)
@@ -8678,15 +8685,6 @@ DRIVER_INIT_MEMBER(segas16b_state,goldnaxe_5704)
 	m_i8751_initial_config = memory_control_5704;
 }
 
-DRIVER_INIT_MEMBER(segas16b_state,goldnaxe_5797)
-{
-	DRIVER_INIT_CALL(generic_5797);
-	m_i8751_vblank_hook = i8751_sim_delegate(&segas16b_state::goldnaxe_i8751_sim, this);
-
-	static const uint8_t memory_control_5797[0x10] =
-		{ 0x02,0x00, 0x00,0x1f, 0x00,0x1e, 0x00,0xff, 0x00,0x20, 0x01,0x10, 0x00,0x14, 0x00,0xc4 };
-	m_i8751_initial_config = memory_control_5797;
-}
 
 DRIVER_INIT_MEMBER(segas16b_state,hwchamp_5521)
 {
@@ -8704,7 +8702,7 @@ DRIVER_INIT_MEMBER(segas16b_state,passshtj_5358)
 DRIVER_INIT_MEMBER(segas16b_state,cencourt_5358)
 {
 	DRIVER_INIT_CALL(passshtj_5358);
-	mc8123_decode(memregion("soundcpu")->base(), m_sound_decrypted_opcodes, memregion("mcu")->base(), 0x8000);
+	mc8123_decode(memregion("soundcpu")->base(), m_sound_decrypted_opcodes, memregion("mc8123")->base(), 0x8000);
 }
 
 DRIVER_INIT_MEMBER(segas16b_state,sdi_5358_small)
@@ -8729,13 +8727,13 @@ DRIVER_INIT_MEMBER(segas16b_state,defense_5358_small)
 DRIVER_INIT_MEMBER(segas16b_state,shinobi4_5521)
 {
 	DRIVER_INIT_CALL(generic_5521);
-	mc8123_decode(memregion("soundcpu")->base(), m_sound_decrypted_opcodes, memregion("mcu")->base(), 0x8000);
+	mc8123_decode(memregion("soundcpu")->base(), m_sound_decrypted_opcodes, memregion("mc8123")->base(), 0x8000);
 }
 
 DRIVER_INIT_MEMBER(segas16b_state,shinobi3_5358)
 {
 	DRIVER_INIT_CALL(generic_5358);
-	mc8123_decode(memregion("soundcpu")->base(), m_sound_decrypted_opcodes, memregion("mcu")->base(), 0x8000);
+	mc8123_decode(memregion("soundcpu")->base(), m_sound_decrypted_opcodes, memregion("mc8123")->base(), 0x8000);
 }
 
 DRIVER_INIT_MEMBER(segas16b_state,sjryuko_5358_small)
@@ -8784,7 +8782,7 @@ GAME( 1987, aliensyn7,  aliensyn, system16b_mc8123,    aliensyn, segas16b_state,
 GAME( 1987, aliensyn3,  aliensyn, system16b_fd1089a,   aliensyn, segas16b_state,generic_5358_small, ROT0,   "Sega", "Alien Syndrome (set 3, System 16B, FD1089A 317-0033)", 0 )
 GAME( 1987, aliensynj,  aliensyn, system16b_fd1089a,   aliensynj,segas16b_state,generic_5358_small, ROT0,   "Sega", "Alien Syndrome (set 6, Japan, new, System 16B, FD1089A 317-0033)", 0 )
 
-GAME( 1988, altbeast,   0,        system16b_i8751,     altbeast, segas16b_state,altbeast_5521,      ROT0,   "Sega", "Altered Beast (set 8) (8751 317-0078)", 0 )
+GAME( 1988, altbeast,   0,        system16b_i8751,     altbeast, segas16b_state,generic_5521,       ROT0,   "Sega", "Altered Beast (set 8) (8751 317-0078)", 0 )
 GAME( 1988, altbeastj,  altbeast, system16b_i8751,     altbeast, segas16b_state,altbeasj_5521,      ROT0,   "Sega", "Juuouki (set 7, Japan) (8751 317-0077)", 0 )
 GAME( 1988, altbeast6,  altbeast, system16b_i8751,     altbeast, segas16b_state,altbeas5_5521,      ROT0,   "Sega", "Altered Beast (set 6) (8751 317-0076)", 0 )
 GAME( 1988, altbeast5,  altbeast, system16b_fd1094,    altbeast, segas16b_state,generic_5521,       ROT0,   "Sega", "Altered Beast (set 5) (FD1094 317-0069)", 0 )
@@ -8828,7 +8826,7 @@ GAME( 1988, exctleag,   0,        system16b_fd1094,    exctleag, segas16b_state,
 GAME( 1989, fpoint,     0,        system16b_fd1094,    fpoint,   segas16b_state,generic_5358,       ROT0,   "Sega", "Flash Point (set 2, Japan) (FD1094 317-0127A)", 0 )
 GAME( 1989, fpoint1,    fpoint,   system16b_fd1094,    fpoint,   segas16b_state,generic_5704,       ROT0,   "Sega", "Flash Point (set 1, Japan) (FD1094 317-0127A)", 0 )
 
-GAME( 1989, goldnaxe,   0,        system16b_i8751_5797,goldnaxe, segas16b_state,goldnaxe_5797,      ROT0,   "Sega", "Golden Axe (set 6, US) (8751 317-123A)", 0 )
+GAME( 1989, goldnaxe,   0,        system16b_i8751_5797,goldnaxe, segas16b_state,generic_5797,       ROT0,   "Sega", "Golden Axe (set 6, US) (8751 317-123A)", 0 )
 GAME( 1989, goldnaxeu,  goldnaxe, system16b_fd1094_5797,goldnaxe,segas16b_state,generic_5797,       ROT0,   "Sega", "Golden Axe (set 5, US) (FD1094 317-0122)", 0 )
 GAME( 1989, goldnaxej,  goldnaxe, system16b_fd1094,    goldnaxe, segas16b_state,generic_5704,       ROT0,   "Sega", "Golden Axe (set 4, Japan) (FD1094 317-0121)", 0 )
 GAME( 1989, goldnaxe3,  goldnaxe, system16b_fd1094,    goldnaxe, segas16b_state,generic_5704,       ROT0,   "Sega", "Golden Axe (set 3, World) (FD1094 317-0120)", 0)
diff --git a/src/mame/drivers/segas32.cpp b/src/mame/drivers/segas32.cpp
index 6129433..d890f22 100644
--- a/src/mame/drivers/segas32.cpp
+++ b/src/mame/drivers/segas32.cpp
@@ -4728,6 +4728,34 @@ ROM_START( svf )
 	ROMX_LOAD( "mpr-16863.ic25", 0x800006, 0x200000, CRC(42338226) SHA1(106636408d5648fb95fbaee06074c57f6a535a82) , ROM_SKIP(6)|ROM_GROUPWORD )
 ROM_END
 
+ROM_START( svfo )
+	ROM_REGION( 0x200000, "mainpcb:maincpu", 0 ) /* v60 code + data */
+	ROM_LOAD_x4( "epr-16872.ic17",     0x000000, 0x020000, CRC(654d8c95) SHA1(0d28d6d8814c07e98fb9c50bd3ecbe17a9dee70a) )
+	ROM_LOAD_x4( "epr-16871.ic8",      0x080000, 0x020000, CRC(e0d0cac0) SHA1(e9a7d0878a38b93681497489a2366f7337a1abf5) )
+	ROM_LOAD16_BYTE( "epr-16865.ic18", 0x100000, 0x080000, CRC(9198ca9f) SHA1(0f6271ce8a07e4ab7fdce38964055510f2ebfd4e) )
+	ROM_LOAD16_BYTE( "epr-16864.ic9",  0x100001, 0x080000, CRC(201a940e) SHA1(e19d76141844dbdedee0698ea50edbb898ab55e9) )
+
+	ROM_REGION( 0x500000, "mainpcb:soundcpu", 0 ) /* sound CPU */
+	ROM_LOAD_x8( "epr-16866.ic36", 0x100000, 0x020000, CRC(74431350) SHA1(d3208b595423b5b0f25ee90db213112a09906f8f) )
+	ROM_LOAD( "mpr-16779.ic35",    0x200000, 0x100000, CRC(7055e859) SHA1(cde27fa4aaf0ee54063ee68794e9a6075581fff5) )
+	ROM_LOAD( "mpr-16778.ic34",    0x300000, 0x100000, CRC(feedaecf) SHA1(25c14ccb85c467dc0c8e85b61f8f86f4396c0cc7) )
+	ROM_LOAD( "mpr-16777.ic24",    0x400000, 0x100000, CRC(14b5d5df) SHA1(1b0b0a31294b1bbc16d2046b374d584a1b00a78c) )
+
+	ROM_REGION( 0x200000, "mainpcb:gfx1", 0 ) /* tiles */
+	ROM_LOAD16_BYTE( "mpr-16784.ic14", 0x000000, 0x100000, CRC(4608efe2) SHA1(9b41aa28f50af770e854ef9fdff1a55da7b7b131) )
+	ROM_LOAD16_BYTE( "mpr-16783.ic5",  0x000001, 0x100000, CRC(042eabe7) SHA1(a11df5c21d85f0c96dbdcaf57be37a79658ad648) )
+
+	ROM_REGION32_BE( 0x1000000, "mainpcb:gfx2", 0 ) /* sprites */
+	ROMX_LOAD( "mpr-16785.ic32", 0x000000, 0x200000, CRC(51f775ce) SHA1(125b40bf47304d37b92e81df5081c81d9af6c8a2) , ROM_SKIP(6)|ROM_GROUPWORD )
+	ROMX_LOAD( "mpr-16787.ic30", 0x000002, 0x200000, CRC(dee7a204) SHA1(29acff4d5dd68609ac46853860788206d18262ab) , ROM_SKIP(6)|ROM_GROUPWORD )
+	ROMX_LOAD( "mpr-16789.ic28", 0x000004, 0x200000, CRC(6b6c8ad3) SHA1(97b0078c851845c31dcf0fe4b2a88393dcdf8988) , ROM_SKIP(6)|ROM_GROUPWORD )
+	ROMX_LOAD( "mpr-16791.ic26", 0x000006, 0x200000, CRC(4f7236da) SHA1(d1c29f6aa82d60a626217f1430bc8a76ef012007) , ROM_SKIP(6)|ROM_GROUPWORD )
+	ROMX_LOAD( "mpr-16860.ic31", 0x800000, 0x200000, CRC(578a7325) SHA1(75a066841fa24952d8ed5ac2d988609295f437a8) , ROM_SKIP(6)|ROM_GROUPWORD )
+	ROMX_LOAD( "mpr-16861.ic29", 0x800002, 0x200000, CRC(d79c3f73) SHA1(e4360efb0964a92cfad8c458a5568709fcc81339) , ROM_SKIP(6)|ROM_GROUPWORD )
+	ROMX_LOAD( "mpr-16862.ic27", 0x800004, 0x200000, CRC(00793354) SHA1(3b37a89c5100d5f92a3567fc8d2003bc9d6fe0cd) , ROM_SKIP(6)|ROM_GROUPWORD )
+	ROMX_LOAD( "mpr-16863.ic25", 0x800006, 0x200000, CRC(42338226) SHA1(106636408d5648fb95fbaee06074c57f6a535a82) , ROM_SKIP(6)|ROM_GROUPWORD )
+ROM_END
+
 /**************************************************************************************************************************
     Super Visual Soccer
     protected via FD1149 317-0222
@@ -5485,7 +5513,8 @@ GAME( 1991, spidman,   0,        sega_system32,     spidman,  segas32_new_state,
 GAME( 1991, spidmanu,  spidman,  sega_system32,     spidmanu, segas32_new_state, spidman,  ROT0, "Sega",   "Spider-Man: The Videogame (US)", MACHINE_IMPERFECT_GRAPHICS )
 GAME( 1991, spidmanj,  spidman,  sega_system32,     spidman,  segas32_new_state, spidman,  ROT0, "Sega",   "Spider-Man: The Videogame (Japan)", MACHINE_IMPERFECT_GRAPHICS )
 
-GAME( 1994, svf,       0,        sega_system32,     svf,      segas32_new_state, svf,      ROT0, "Sega",   "Super Visual Football: European Sega Cup", MACHINE_IMPERFECT_GRAPHICS )
+GAME( 1994, svf,       0,        sega_system32,     svf,      segas32_new_state, svf,      ROT0, "Sega",   "Super Visual Football: European Sega Cup (Rev A)", MACHINE_IMPERFECT_GRAPHICS )
+GAME( 1994, svfo,      svf,      sega_system32,     svf,      segas32_new_state, svf,      ROT0, "Sega",   "Super Visual Football: European Sega Cup", MACHINE_IMPERFECT_GRAPHICS )
 GAME( 1994, svs,       svf,      sega_system32,     svf,      segas32_new_state, svf,      ROT0, "Sega",   "Super Visual Soccer: Sega Cup (US)", MACHINE_IMPERFECT_GRAPHICS )
 GAME( 1994, jleague,   svf,      sega_system32,     svf,      segas32_new_state, jleague,  ROT0, "Sega",   "The J.League 1994 (Japan, Rev A)", MACHINE_IMPERFECT_GRAPHICS )
 GAME( 1994, jleagueo,  svf,      sega_system32,     svf,      segas32_new_state, jleague,  ROT0, "Sega",   "The J.League 1994 (Japan)", MACHINE_IMPERFECT_GRAPHICS )
diff --git a/src/mame/drivers/seta.cpp b/src/mame/drivers/seta.cpp
index 3c8e51e..f292518 100644
--- a/src/mame/drivers/seta.cpp
+++ b/src/mame/drivers/seta.cpp
@@ -1967,7 +1967,7 @@ READ16_MEMBER(seta_state::extra_r)
 
 static ADDRESS_MAP_START( wrofaero_map, AS_PROGRAM, 16, seta_state )
 	AM_RANGE(0x000000, 0x1fffff) AM_ROM                             // ROM (up to 2MB)
-	AM_RANGE(0x200000, 0x20ffff) AM_RAM AM_SHARE("workram")     // RAM (pointer for zombraid crosshair hack)
+	AM_RANGE(0x200000, 0x20ffff) AM_RAM                             // RAM
 	AM_RANGE(0x210000, 0x21ffff) AM_RAM                             // RAM (gundhara)
 	AM_RANGE(0x300000, 0x30ffff) AM_RAM                             // RAM (wrofaero only?)
 	AM_RANGE(0x400000, 0x400001) AM_READ_PORT("P1")                 // P1
@@ -2001,6 +2001,11 @@ static ADDRESS_MAP_START( wrofaero_map, AS_PROGRAM, 16, seta_state )
 	AM_RANGE(0xf00000, 0xf00001) AM_WRITENOP                        // ? Sound  IRQ Ack
 ADDRESS_MAP_END
 
+static ADDRESS_MAP_START( zombraid_map, AS_PROGRAM, 16, seta_state )
+	AM_IMPORT_FROM( wrofaero_map )
+	AM_RANGE(0x300000, 0x30ffff) AM_RAM AM_SHARE("nvram")           // actually 8K x8 SRAM
+ADDRESS_MAP_END
+
 READ16_MEMBER(seta_state::zingzipbl_unknown_r)
 {
 	return 0x0000;
@@ -8555,6 +8560,18 @@ static MACHINE_CONFIG_START( gundhara, seta_state )
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
 MACHINE_CONFIG_END
 
+/***************************************************************************
+                                Zombie Raid
+***************************************************************************/
+
+static MACHINE_CONFIG_DERIVED( zombraid, gundhara )
+
+	/* basic machine hardware */
+	MCFG_CPU_MODIFY("maincpu")
+	MCFG_CPU_PROGRAM_MAP(zombraid_map)
+
+	MCFG_NVRAM_ADD_0FILL("nvram")
+MACHINE_CONFIG_END
 
 /***************************************************************************
                                 J.J.Squawkers
@@ -10674,7 +10691,6 @@ ROM_START( jjsquawkb )
 	ROM_COPY( "gfxtemp", 0x000000, 0x000000, 0x100000 )
 	ROM_COPY( "gfxtemp", 0x200000, 0x100000, 0x100000 )
 
-
 	ROM_REGION( 0x200000, "gfx3", 0 )   /* Layer 2 */
 	ROM_COPY( "gfxtemp", 0x100000, 0x000000, 0x100000 )
 	ROM_COPY( "gfxtemp", 0x300000, 0x100000, 0x100000 )
@@ -10706,6 +10722,32 @@ ROM_START( jjsquawkb2 ) /* PCB was P0-078A, which was a Blandia board converted
 	ROM_LOAD( "u70.10l", 0x000000, 0x100000, CRC(181a55b8) SHA1(6fa404f85bad93cc15e80feb61d19bed84602b82) ) /* fe2001005.u69 + fe2001006.u70 from jjsquawk */
 ROM_END
 
+ROM_START( simpsonjr ) /* bootleg of J. J. Squawkers by Daigom */
+	ROM_REGION( 0x200000, "maincpu", 0 )        /* 68000 Code */
+	ROM_LOAD16_WORD_SWAP( "4.bin", 0x000000, 0x080000, CRC(469cc203) SHA1(4ecd8dce936f24acb149ef2fdf34595bd4a20a74) )
+	ROM_LOAD16_WORD_SWAP( "3.bin", 0x100000, 0x080000, CRC(740a7366) SHA1(2539f9a9b4fed1a1e2c354d144b8d455ed4bc144) )
+
+	ROM_REGION( 0x800000, "gfxtemp", 0  )
+	ROM_LOAD( "5.bin",  0x000000, 0x400000, CRC(82952780) SHA1(83b61c726dd102491fe338036531f7653b0edefc) )
+	ROM_LOAD( "6.bin",  0x400000, 0x400000, CRC(5a22bb87) SHA1(e5f91af685eb9331c5f00d81eca6dca177a9c860) )
+
+	ROM_REGION( 0x400000, "gfx1", 0 )   /* Sprites */
+	ROM_COPY( "gfxtemp", 0x600000, 0x000000, 0x200000 )
+	ROM_COPY( "gfxtemp", 0x200000, 0x200000, 0x200000 )
+
+	ROM_REGION( 0x200000, "gfx2", 0 )   /* Layer 1 */
+	ROM_COPY( "gfxtemp", 0x400000, 0x000000, 0x100000 )
+	ROM_COPY( "gfxtemp", 0x000000, 0x100000, 0x100000 )
+
+	ROM_REGION( 0x200000, "gfx3", 0 )   /* Layer 2 */
+	ROM_COPY( "gfxtemp", 0x500000, 0x000000, 0x100000 )
+	ROM_COPY( "gfxtemp", 0x100000, 0x100000, 0x100000 )
+
+	ROM_REGION( 0x100000, "x1snd", 0 )  /* Samples */
+	ROM_LOAD( "1.bin", 0x000000, 0x080000, CRC(d99f2879) SHA1(66e83a6bc9093d19c72bd8ef1ec0523cfe218250) )
+	ROM_LOAD( "2.bin", 0x080000, 0x080000, CRC(9df1e478) SHA1(f41b55821187b417ad09e4a1f439c01a107d2674) )
+ROM_END
+
 ROM_START( kamenrid )
 	ROM_REGION( 0x080000, "maincpu", 0 )        /* 68000 Code */
 	ROM_LOAD16_WORD_SWAP( "fj001003.25", 0x000000, 0x080000, CRC(9b65d1b9) SHA1(a9183f817dbd1721cbb1a9049ca2bfc6acdf9f4a) )
@@ -10878,44 +10920,44 @@ ROM_END
    same factory as normal boards same as daiohc.  Modified layout allowing
    split ROMs */
 ROM_START( gundharac )
-		ROM_REGION( 0x200000, "maincpu", 0 )        /* 68000 Code */
-		ROM_LOAD16_BYTE( "4.U3",  0x000000, 0x080000, CRC(14e9970a) SHA1(31964bd290cc94c40684adf3a5d129b1c3addc3b) )
-		ROM_LOAD16_BYTE( "2.U4",  0x000001, 0x080000, CRC(96dfc658) SHA1(f570bc49758535eb00d93ecce9f75832f97a0d8d) )
-		ROM_LOAD16_BYTE( "3.U103", 0x100000, 0x080000, CRC(312f58e2) SHA1(a74819d2f84a00c233489893f12c9ab1a98459cf) )
-		ROM_LOAD16_BYTE( "1.U102", 0x100001, 0x080000, CRC(8d23a23c) SHA1(9e9a6488db424c81a97edcb7115cc070fe35c077) )
+	ROM_REGION( 0x200000, "maincpu", 0 )        /* 68000 Code */
+	ROM_LOAD16_BYTE( "4.U3",  0x000000, 0x080000, CRC(14e9970a) SHA1(31964bd290cc94c40684adf3a5d129b1c3addc3b) )
+	ROM_LOAD16_BYTE( "2.U4",  0x000001, 0x080000, CRC(96dfc658) SHA1(f570bc49758535eb00d93ecce9f75832f97a0d8d) )
+	ROM_LOAD16_BYTE( "3.U103", 0x100000, 0x080000, CRC(312f58e2) SHA1(a74819d2f84a00c233489893f12c9ab1a98459cf) )
+	ROM_LOAD16_BYTE( "1.U102", 0x100001, 0x080000, CRC(8d23a23c) SHA1(9e9a6488db424c81a97edcb7115cc070fe35c077) )
 
-		ROM_REGION( 0x800000, "gfx1", 0 )   /* Sprites */
+	ROM_REGION( 0x800000, "gfx1", 0 )   /* Sprites */
 	ROM_LOAD16_BYTE( "19.U140", 0x000000, 0x080000, CRC(32d92c28) SHA1(7ba67f715f094aacf2dc2399809e4dfc7e4ca241) )
-		ROM_LOAD16_BYTE( "23.U142", 0x000001, 0x080000, CRC(ff44db9b) SHA1(76ecd3ce3b6b33f3ae0b0454d58cf37d545dd72c) )
-		ROM_LOAD16_BYTE( "21.U141", 0x100000, 0x080000, CRC(1901dc08) SHA1(b19428a7510d6e28a39bdf6ecc9732e3c2d19214) )
-		ROM_LOAD16_BYTE( "25.U143", 0x100001, 0x080000, CRC(877289a2) SHA1(7482320e319d7b641fabba5aeeaa1237b693a219) )
+	ROM_LOAD16_BYTE( "23.U142", 0x000001, 0x080000, CRC(ff44db9b) SHA1(76ecd3ce3b6b33f3ae0b0454d58cf37d545dd72c) )
+	ROM_LOAD16_BYTE( "21.U141", 0x100000, 0x080000, CRC(1901dc08) SHA1(b19428a7510d6e28a39bdf6ecc9732e3c2d19214) )
+	ROM_LOAD16_BYTE( "25.U143", 0x100001, 0x080000, CRC(877289a2) SHA1(7482320e319d7b641fabba5aeeaa1237b693a219) )
 	ROM_LOAD16_BYTE( "18.U140-B", 0x200000, 0x080000, CRC(4f023fb0) SHA1(815765c9783e44762bf57a3fbfad4385c316343a) )
 	ROM_LOAD16_BYTE( "22.U142-B", 0x200001, 0x080000, CRC(6f3fe7e7) SHA1(71bc347c06678f4ae7850799da6346c6447bf3c0) )
 	ROM_LOAD16_BYTE( "20.U141-B", 0x300000, 0x080000, CRC(7f1932e0) SHA1(13262a7322ad29cf7c85461204a3518e900c6145) )
 	ROM_LOAD16_BYTE( "24.U143-B", 0x300001, 0x080000, CRC(066a2e2b) SHA1(186729918a89535484ab86dd58caf20ccce81501) )
-		ROM_LOAD16_BYTE( "9.U144", 0x400000, 0x080000, CRC(6b4a531f) SHA1(701d6b2d87a742c8a2ab36331bd843dcd3309eae) )
-		ROM_LOAD16_BYTE( "13.U146", 0x400001, 0x080000, CRC(45be3df4) SHA1(36667bf5e4b80d17a9d7b6ce4df7498f94681c46) )
-		ROM_LOAD16_BYTE( "11.U145", 0x500000, 0x080000, CRC(f5210aa5) SHA1(4834d905f699dbec1cdacea6b320271c291aa2a7) )
-		ROM_LOAD16_BYTE( "15.U147", 0x500001, 0x080000, CRC(17003119) SHA1(a2edd65c98bc654b541dad3e3783d90931c97597) )
-		ROM_LOAD16_BYTE( "8.U144-B", 0x600000, 0x080000, CRC(ad9d9338) SHA1(33d6c881a20e2150017cc26f929473291e561718) )
-		ROM_LOAD16_BYTE( "12.U146-B", 0x600001, 0x080000, CRC(0fd4c062) SHA1(7f418d43d9ba884c504f6fe3c04b11724412ac6b) )
-		ROM_LOAD16_BYTE( "10.U145-B", 0x700000, 0x080000, CRC(7c5d12b9) SHA1(6ee45c4da6994540852153752e2818a8ea8ecf1a) )
-		ROM_LOAD16_BYTE( "14.U147-B", 0x700001, 0x080000, CRC(5a8af50f) SHA1(3b7937ba720fcbbc5e29c1b95a97c29e8ff5490a) )
-
-		ROM_REGION( 0x200000, "gfx2", 0 )   /* Layer 1 */
-		ROM_LOAD16_BYTE( "5.U148", 0x000000, 0x080000, CRC(0c740f9b) SHA1(f6d135c3318ff0d50d40921aa108b1b332c1a086) )
-		ROM_LOAD16_BYTE( "6.U150", 0x000001, 0x080000, CRC(ba60eb98) SHA1(7204269816332bbb3401d9f20a513372ffe78500) )
-		ROM_LOAD16_BYTE( "7.U154", 0x100000, 0x080000, CRC(b768e666) SHA1(473fa52c16c0a9f321e6429947a3e0fc1ef22f7e) )
-
-		ROM_REGION( 0x400000, "gfx3", 0 )   /* Layer 2 */
-		ROM_LOAD16_BYTE( "26.U164", 0x000000, 0x080000, CRC(be3ccaba) SHA1(98f8b83cbed00932866375d21f86ee5c9bddb2a6) )
-		ROM_LOAD16_BYTE( "28.U166", 0x000001, 0x080000, CRC(8a650a4e) SHA1(1f6eda27b39ad052e3d9a8a72cb0a072e7be4487) )
-		ROM_LOAD16_BYTE( "27.U165", 0x100000, 0x080000, CRC(47994ff0) SHA1(25211a9af01f77788578bb524619d95b5b86e241) )
-		ROM_LOAD16_BYTE( "29.U167", 0x100001, 0x080000, CRC(453c3d3f) SHA1(151528b6b1e7f8c059d67dbaca61e7c382e9ce04) )
+	ROM_LOAD16_BYTE( "9.U144", 0x400000, 0x080000, CRC(6b4a531f) SHA1(701d6b2d87a742c8a2ab36331bd843dcd3309eae) )
+	ROM_LOAD16_BYTE( "13.U146", 0x400001, 0x080000, CRC(45be3df4) SHA1(36667bf5e4b80d17a9d7b6ce4df7498f94681c46) )
+	ROM_LOAD16_BYTE( "11.U145", 0x500000, 0x080000, CRC(f5210aa5) SHA1(4834d905f699dbec1cdacea6b320271c291aa2a7) )
+	ROM_LOAD16_BYTE( "15.U147", 0x500001, 0x080000, CRC(17003119) SHA1(a2edd65c98bc654b541dad3e3783d90931c97597) )
+	ROM_LOAD16_BYTE( "8.U144-B", 0x600000, 0x080000, CRC(ad9d9338) SHA1(33d6c881a20e2150017cc26f929473291e561718) )
+	ROM_LOAD16_BYTE( "12.U146-B", 0x600001, 0x080000, CRC(0fd4c062) SHA1(7f418d43d9ba884c504f6fe3c04b11724412ac6b) )
+	ROM_LOAD16_BYTE( "10.U145-B", 0x700000, 0x080000, CRC(7c5d12b9) SHA1(6ee45c4da6994540852153752e2818a8ea8ecf1a) )
+	ROM_LOAD16_BYTE( "14.U147-B", 0x700001, 0x080000, CRC(5a8af50f) SHA1(3b7937ba720fcbbc5e29c1b95a97c29e8ff5490a) )
+
+	ROM_REGION( 0x200000, "gfx2", 0 )   /* Layer 1 */
+	ROM_LOAD16_BYTE( "5.U148", 0x000000, 0x080000, CRC(0c740f9b) SHA1(f6d135c3318ff0d50d40921aa108b1b332c1a086) )
+	ROM_LOAD16_BYTE( "6.U150", 0x000001, 0x080000, CRC(ba60eb98) SHA1(7204269816332bbb3401d9f20a513372ffe78500) )
+	ROM_LOAD16_BYTE( "7.U154", 0x100000, 0x080000, CRC(b768e666) SHA1(473fa52c16c0a9f321e6429947a3e0fc1ef22f7e) )
+
+	ROM_REGION( 0x400000, "gfx3", 0 )   /* Layer 2 */
+	ROM_LOAD16_BYTE( "26.U164", 0x000000, 0x080000, CRC(be3ccaba) SHA1(98f8b83cbed00932866375d21f86ee5c9bddb2a6) )
+	ROM_LOAD16_BYTE( "28.U166", 0x000001, 0x080000, CRC(8a650a4e) SHA1(1f6eda27b39ad052e3d9a8a72cb0a072e7be4487) )
+	ROM_LOAD16_BYTE( "27.U165", 0x100000, 0x080000, CRC(47994ff0) SHA1(25211a9af01f77788578bb524619d95b5b86e241) )
+	ROM_LOAD16_BYTE( "29.U167", 0x100001, 0x080000, CRC(453c3d3f) SHA1(151528b6b1e7f8c059d67dbaca61e7c382e9ce04) )
 	ROM_LOAD16_BYTE( "16.U152", 0x200000, 0x080000, CRC(5ccc500b) SHA1(d3a2a5658cac8d788e0a1189c184309b8394b10a) )
 	ROM_LOAD16_BYTE( "17.U153", 0x300000, 0x080000, CRC(5586d086) SHA1(e43d5e8834701f40389400f68a99353e67598f6d) )
 
-		ROM_REGION( 0x100000, "x1snd", 0 )  /* Samples */
+	ROM_REGION( 0x100000, "x1snd", 0 )  /* Samples */
 	ROM_LOAD( "30.U69", 0x000000, 0x080000, CRC(3111a98a) SHA1(75e17a0113060a10551b2b8c17b19890eb7aa0a6) )
 	ROM_LOAD( "31.U70", 0x080000, 0x080000, CRC(30cb2524) SHA1(85deb83262bbe481404705e163e5eb9362985b01) )
 ROM_END
@@ -10963,6 +11005,9 @@ ROM_START( zombraid )
 	// skip 80000-fffff (banked region)
 	ROM_CONTINUE(            0x100000, 0x180000  )
 	ROM_LOAD( "fy001011.a",  0x280000, 0x200000, CRC(e3c431de) SHA1(1030adacbbfabc00231417e09f3de40e3052f65c) )
+
+	ROM_REGION(0x10000, "nvram", 0)
+	ROM_LOAD( "nvram.bin",  0x0000, 0x10000, CRC(1a4b2ee8) SHA1(9a14fb2089fef9d13e0a5fe0a83eb7bae51fe1ae) )
 ROM_END
 
 /* Notes about the Proto/Test roms:
@@ -11024,6 +11069,9 @@ ROM_START( zombraidp ) /* Prototype or test board version.  Data matches release
 	ROM_LOAD( "u161_master_snd_5_599c.u161", 0x300000, 0x080000, CRC(1793dd13) SHA1(1b5b3c50e6df399c3e334c08be5313eef7d7ed95) )
 	ROM_LOAD( "u162_master_snd_6_6d2e.u162", 0x380000, 0x080000, CRC(2ece241f) SHA1(1ebe4dd788799ec10c2eddf02f9bdaee8457993b) )
 	ROM_LOAD( "u163_master_snd_7_c733.u163", 0x400000, 0x080000, CRC(d90f78b2) SHA1(e847eba6a4d6c1a3044041a9d32b6b534fb45307) )
+
+	ROM_REGION(0x10000, "nvram", 0)
+	ROM_LOAD( "nvram.bin",  0x0000, 0x10000, CRC(1a4b2ee8) SHA1(9a14fb2089fef9d13e0a5fe0a83eb7bae51fe1ae) )
 ROM_END
 
 ROM_START( zombraidpj ) /* Prototype or test board version.  Data matches released MASK rom version */
@@ -11069,6 +11117,9 @@ ROM_START( zombraidpj ) /* Prototype or test board version.  Data matches releas
 	ROM_LOAD( "u161_master_snd_5_599c.u161", 0x300000, 0x080000, CRC(1793dd13) SHA1(1b5b3c50e6df399c3e334c08be5313eef7d7ed95) )
 	ROM_LOAD( "u162_master_snd_6_6d2e.u162", 0x380000, 0x080000, CRC(2ece241f) SHA1(1ebe4dd788799ec10c2eddf02f9bdaee8457993b) )
 	ROM_LOAD( "u163_master_snd_7_c733.u163", 0x400000, 0x080000, CRC(d90f78b2) SHA1(e847eba6a4d6c1a3044041a9d32b6b534fb45307) )
+
+	ROM_REGION(0x10000, "nvram", 0)
+	ROM_LOAD( "nvram.bin",  0x0000, 0x10000, CRC(1a4b2ee8) SHA1(9a14fb2089fef9d13e0a5fe0a83eb7bae51fe1ae) )
 ROM_END
 
 ROM_START( madshark )
@@ -11688,6 +11739,7 @@ GAME( 1993, jjsquawk, 0,        jjsquawk, jjsquawk, driver_device, 0,        ROT
 GAME( 1993, jjsquawko,jjsquawk, jjsquawk, jjsquawk, driver_device, 0,        ROT0,   "Athena / Able",          "J. J. Squawkers (older)", MACHINE_IMPERFECT_SOUND )
 GAME( 1993, jjsquawkb,jjsquawk, jjsquawb, jjsquawk, driver_device, 0,        ROT0,   "bootleg",                "J. J. Squawkers (bootleg)", MACHINE_IMPERFECT_SOUND )
 GAME( 1993, jjsquawkb2,jjsquawk,jjsquawk, jjsquawk, driver_device, 0,        ROT0,   "bootleg",                "J. J. Squawkers (bootleg, Blandia Conversion)", MACHINE_IMPERFECT_SOUND )
+GAME( 2003, simpsonjr, jjsquawk,jjsquawb, jjsquawk, driver_device, 0,        ROT0,   "bootleg",                "Simpson Junior (bootleg of J. J. Squawkers)", MACHINE_IMPERFECT_SOUND )
 
 GAME( 1993, kamenrid, 0,        kamenrid, kamenrid, driver_device, 0,        ROT0,   "Banpresto / Toei",       "Masked Riders Club Battle Race", 0 )
 
@@ -11725,8 +11777,8 @@ GAME( 1995, gundharac, gundhara,gundhara, gundhara, driver_device, 0,        ROT
 
 GAME( 1995, sokonuke, 0,        extdwnhl, sokonuke, driver_device, 0,        ROT0,   "Sammy Industries",       "Sokonuke Taisen Game (Japan)", MACHINE_IMPERFECT_SOUND )
 
-GAME( 1995, zombraid, 0,        gundhara, zombraid, seta_state, zombraid, ROT0,   "American Sammy",            "Zombie Raid (9/28/95, US)", MACHINE_NO_COCKTAIL )
-GAME( 1995, zombraidp,zombraid, gundhara, zombraid, seta_state, zombraid, ROT0,   "American Sammy",            "Zombie Raid (9/28/95, US, prototype PCB)", MACHINE_NO_COCKTAIL ) // actual code is same as the released version
-GAME( 1995, zombraidpj,zombraid,gundhara, zombraid, seta_state, zombraid, ROT0,   "Sammy Industries Co.,Ltd.", "Zombie Raid (9/28/95, Japan, prototype PCB)", MACHINE_NO_COCKTAIL ) // just 3 bytes different from above
+GAME( 1995, zombraid, 0,        zombraid, zombraid, seta_state, zombraid, ROT0,   "American Sammy",            "Zombie Raid (9/28/95, US)", MACHINE_NO_COCKTAIL )
+GAME( 1995, zombraidp,zombraid, zombraid, zombraid, seta_state, zombraid, ROT0,   "American Sammy",            "Zombie Raid (9/28/95, US, prototype PCB)", MACHINE_NO_COCKTAIL ) // actual code is same as the released version
+GAME( 1995, zombraidpj,zombraid,zombraid, zombraid, seta_state, zombraid, ROT0,   "Sammy Industries Co.,Ltd.", "Zombie Raid (9/28/95, Japan, prototype PCB)", MACHINE_NO_COCKTAIL ) // just 3 bytes different from above
 
 GAME( 1996, crazyfgt, 0,        crazyfgt, crazyfgt, seta_state, crazyfgt, ROT0,   "Subsino",                   "Crazy Fight", MACHINE_UNEMULATED_PROTECTION | MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND )
diff --git a/src/mame/drivers/sfkick.cpp b/src/mame/drivers/sfkick.cpp
index 291f60b..f5211ae 100644
--- a/src/mame/drivers/sfkick.cpp
+++ b/src/mame/drivers/sfkick.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /*
   Super Free Kick / Spinkick by HEC (Haesung Enterprise Co.)
diff --git a/src/mame/drivers/sg1000a.cpp b/src/mame/drivers/sg1000a.cpp
index bd75fd4..6daec4a 100644
--- a/src/mame/drivers/sg1000a.cpp
+++ b/src/mame/drivers/sg1000a.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /*********************************************************
 Sega hardware based on their SG-1000 console
diff --git a/src/mame/drivers/shootout.cpp b/src/mame/drivers/shootout.cpp
index 13c31bd..e839031 100644
--- a/src/mame/drivers/shootout.cpp
+++ b/src/mame/drivers/shootout.cpp
@@ -13,9 +13,14 @@
     arm?
 
     Shoot Out (Korean bootleg) is based on the earlier DE-0203 board but
-    strangely features the same encryption as used on the DE-0219 board.  It
+    strangely features the same encryption as used on the DE-0219 board. It
     also has some edited graphics.
 
+    The DE-0219 PCB seems to have only one 12 MHz XTAL, some images with recognizable XTAL value can be found here:
+    - http://www.jammarcade.net/images/2016/04/Shootout.jpg
+    - http://thumbs.picclick.com/00/s/MTIwMFgxNjAw/z/7iIAAOSw5ClXxbrB/$/Data-East-Shootout-Arcade-Video-Game-Pcb-Circuit-_57.jpg
+
+
     Driver by:
         Ernesto Corvi (ernesto at imagina.com)
         Phil Stroffolino
@@ -23,8 +28,9 @@
 
     TODO:
 
-    - Fix coin counter
-    - Lots of unmapped memory reads
+    - Lots of unmapped memory reads and writes (sprram or vram mirrors, perhaps...), bg_vram is also read.
+    - Does the korean bootleg really have the DECO 222 CPU? I think it should use the shootclr.003 prom to decrypt the opcodes.
+      Something like -> rom [addr] = (rom [addr] & 0x0F) | proms [rom [addr] >> 4]]);
 
 *******************************************************************************/
 
@@ -49,10 +55,19 @@ WRITE8_MEMBER(shootout_state::bankswitch_w)
 	membank("bank1")->set_entry(data & 0x0f);
 }
 
+READ8_MEMBER(shootout_state::sound_cpu_command_r)
+{
+	m_audiocpu->set_input_line (INPUT_LINE_NMI, CLEAR_LINE);
+	return (m_soundlatch->read (space, 0));
+}
+
 WRITE8_MEMBER(shootout_state::sound_cpu_command_w)
 {
 	m_soundlatch->write( space, offset, data );
-	m_audiocpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE );
+	m_audiocpu->set_input_line(INPUT_LINE_NMI, ASSERT_LINE);
+
+	// Allow the other CPU to reply. This fixes the missing music on the title screen (parent set).
+	space.device ().execute ().spin_until_time (attotime :: from_usec (200));
 }
 
 WRITE8_MEMBER(shootout_state::flipscreen_w)
@@ -60,9 +75,27 @@ WRITE8_MEMBER(shootout_state::flipscreen_w)
 	flip_screen_set(data & 0x01);
 }
 
+/*
+    This is actually a double BCD counter (2 BCD digits packet in a byte)...
+    The first write is always 0x40, then when a coin is inserted it starts to count from 0x01 up to 0x99.
+    When it reaches 99 credits, 0x99 is always written...
+
+    On the shootoutj and shootoutb sets, it works as above but it counts up to 0x09 instead of 0x99 (Single BCD digit).
+
+    Note:
+    This should be an input for a BCD to 7-segment decoder (e.g. a 74LS47), but all the PCBs I've seen don't have 'onboard'
+    display(s), so this was implemented as normal "coin counter" (after all, they both have the same goal: count credits ;))
+*/
 WRITE8_MEMBER(shootout_state::coincounter_w)
 {
-	machine().bookkeeping().coin_counter_w(0, data);
+	if (data != m_ccnt_old_val)
+	{
+		// Do a coin pulse
+		machine().bookkeeping().coin_counter_w(0, 0);
+		machine().bookkeeping().coin_counter_w(0, 1);
+
+		m_ccnt_old_val = data;
+	}
 }
 
 /*******************************************************************************/
@@ -78,7 +111,7 @@ static ADDRESS_MAP_START( shootout_map, AS_PROGRAM, 8, shootout_state )
 	AM_RANGE(0x2000, 0x27ff) AM_RAM_WRITE(textram_w) AM_SHARE("textram")
 	AM_RANGE(0x2800, 0x2fff) AM_RAM_WRITE(videoram_w) AM_SHARE("videoram")
 	AM_RANGE(0x4000, 0x7fff) AM_ROMBANK("bank1")
-	AM_RANGE(0x8000, 0xffff) AM_ROM
+	AM_RANGE(0x8000, 0xffff) AM_ROM AM_REGION("maincpu", 0x0000)
 ADDRESS_MAP_END
 
 static ADDRESS_MAP_START( shootouj_map, AS_PROGRAM, 8, shootout_state )
@@ -87,13 +120,14 @@ static ADDRESS_MAP_START( shootouj_map, AS_PROGRAM, 8, shootout_state )
 	AM_RANGE(0x1001, 0x1001) AM_READ_PORT("P1")
 	AM_RANGE(0x1002, 0x1002) AM_READ_PORT("P2")
 	AM_RANGE(0x1003, 0x1003) AM_READ_PORT("DSW2")
+	AM_RANGE(0x1004, 0x17ff) AM_RAM
 	AM_RANGE(0x1800, 0x1800) AM_WRITE(coincounter_w)
 	AM_RANGE(0x2000, 0x21ff) AM_RAM AM_SHARE("spriteram")
 	AM_RANGE(0x2800, 0x2801) AM_DEVREADWRITE("ymsnd", ym2203_device, read, write)
 	AM_RANGE(0x3000, 0x37ff) AM_RAM_WRITE(textram_w) AM_SHARE("textram")
 	AM_RANGE(0x3800, 0x3fff) AM_RAM_WRITE(videoram_w) AM_SHARE("videoram")
 	AM_RANGE(0x4000, 0x7fff) AM_ROMBANK("bank1")
-	AM_RANGE(0x8000, 0xffff) AM_ROM
+	AM_RANGE(0x8000, 0xffff) AM_ROM AM_REGION("maincpu", 0x0000)
 ADDRESS_MAP_END
 
 /*******************************************************************************/
@@ -102,9 +136,9 @@ ADDRESS_MAP_END
 static ADDRESS_MAP_START( shootout_sound_map, AS_PROGRAM, 8, shootout_state )
 	AM_RANGE(0x0000, 0x07ff) AM_RAM
 	AM_RANGE(0x4000, 0x4001) AM_DEVREADWRITE("ymsnd", ym2203_device, read, write)
-	AM_RANGE(0xa000, 0xa000) AM_DEVREAD("soundlatch", generic_latch_8_device, read)
-	AM_RANGE(0xc000, 0xffff) AM_ROM
-	AM_RANGE(0xd000, 0xd000) AM_WRITENOP // unknown, NOT irq/nmi mask
+	AM_RANGE(0xa000, 0xa000) AM_READ(sound_cpu_command_r)
+	AM_RANGE(0xc000, 0xffff) AM_ROM AM_REGION("audiocpu", 0x0000)
+	AM_RANGE(0xd000, 0xd000) AM_WRITENOP // Unknown, NOT irq/nmi mask (Always 0x80 ???)
 ADDRESS_MAP_END
 
 /*******************************************************************************/
@@ -173,8 +207,8 @@ static INPUT_PORTS_START( shootout )
 	PORT_DIPSETTING(    0x20, DEF_STR( Normal ) )
 	PORT_DIPSETTING(    0x10, DEF_STR( Hard ) )
 	PORT_DIPSETTING(    0x00, DEF_STR( Very_Hard ) )
-	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SPECIAL ) /* this is set when either coin is inserted */
-	PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_VBLANK("screen")
+	PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_SPECIAL ) // This needs to be low to allows both coins to be accepted...
+	PORT_BIT( 0x80, IP_ACTIVE_LOW,  IPT_CUSTOM ) PORT_VBLANK("screen")
 INPUT_PORTS_END
 
 static INPUT_PORTS_START( shootouj )
@@ -231,23 +265,26 @@ static GFXDECODE_START( shootout )
 	GFXDECODE_ENTRY( "gfx3", 0, tile_layout,   0,        16 ) /* tiles */
 GFXDECODE_END
 
-
+void shootout_state::machine_reset ()
+{
+	m_ccnt_old_val = 0x40;
+}
 
 static MACHINE_CONFIG_START( shootout, shootout_state )
 
 	/* basic machine hardware */
-	MCFG_CPU_ADD("maincpu", DECO_222, 2000000)  /* 2 MHz? */
+	MCFG_CPU_ADD("maincpu", DECO_222, XTAL_12MHz / 6) // 2 MHz?
 	MCFG_CPU_PROGRAM_MAP(shootout_map)
 
-	MCFG_CPU_ADD("audiocpu", M6502, 1500000)
+	MCFG_CPU_ADD("audiocpu", M6502, XTAL_12MHz / 8) // 1.5 MHz
 	MCFG_CPU_PROGRAM_MAP(shootout_sound_map)
 
 	/* video hardware */
 	MCFG_SCREEN_ADD("screen", RASTER)
-	MCFG_SCREEN_REFRESH_RATE(60)
-	MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500) /* not accurate */)
-	MCFG_SCREEN_SIZE(32*8, 32*8)
-	MCFG_SCREEN_VISIBLE_AREA(0*8, 32*8-1, 1*8, 31*8-1)
+
+	// Guessed parameters based on the 12 MHz XTAL, but they seem resonable (TODO: Real PCB measurements)
+	MCFG_SCREEN_RAW_PARAMS (XTAL_12MHz / 2, 384, 0, 256, 262, 8, 248)
+
 	MCFG_SCREEN_UPDATE_DRIVER(shootout_state, screen_update_shootout)
 	MCFG_SCREEN_PALETTE("palette")
 
@@ -260,24 +297,24 @@ static MACHINE_CONFIG_START( shootout, shootout_state )
 
 	MCFG_GENERIC_LATCH_8_ADD("soundlatch")
 
-	MCFG_SOUND_ADD("ymsnd", YM2203, 1500000)
+	MCFG_SOUND_ADD("ymsnd", YM2203, XTAL_12MHz / 8) // 1.5 MHz
 	MCFG_YM2203_IRQ_HANDLER(INPUTLINE("audiocpu", M6502_IRQ_LINE))
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
 MACHINE_CONFIG_END
 
 
 static MACHINE_CONFIG_START( shootouj, shootout_state )
 
 	/* basic machine hardware */
-	MCFG_CPU_ADD("maincpu", M6502, 2000000) /* 2 MHz? */
+	MCFG_CPU_ADD("maincpu", M6502, XTAL_12MHz / 6) // 2 MHz? (Assuming the same XTAL as DE-0219 pcb)
 	MCFG_CPU_PROGRAM_MAP(shootouj_map)
 
 	/* video hardware */
 	MCFG_SCREEN_ADD("screen", RASTER)
-	MCFG_SCREEN_REFRESH_RATE(60)
-	MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500) /* not accurate */)
-	MCFG_SCREEN_SIZE(32*8, 32*8)
-	MCFG_SCREEN_VISIBLE_AREA(0*8, 32*8-1, 1*8, 31*8-1)
+
+	// Guessed parameters based on the 12 MHz XTAL, but they seem resonable (TODO: Real PCB measurements)
+	MCFG_SCREEN_RAW_PARAMS (XTAL_12MHz / 2, 384, 0, 256, 262, 8, 248)
+
 	MCFG_SCREEN_UPDATE_DRIVER(shootout_state, screen_update_shootouj)
 	MCFG_SCREEN_PALETTE("palette")
 
@@ -290,31 +327,30 @@ static MACHINE_CONFIG_START( shootouj, shootout_state )
 
 	MCFG_GENERIC_LATCH_8_ADD("soundlatch")
 
-	MCFG_SOUND_ADD("ymsnd", YM2203, 1500000)
+	MCFG_SOUND_ADD("ymsnd", YM2203, XTAL_12MHz / 8) // 1.5 MHz (Assuming the same XTAL as DE-0219 pcb)
 	MCFG_YM2203_IRQ_HANDLER(INPUTLINE("maincpu", M6502_IRQ_LINE))
 	MCFG_AY8910_PORT_A_WRITE_CB(WRITE8(shootout_state, bankswitch_w))
 	MCFG_AY8910_PORT_B_WRITE_CB(WRITE8(shootout_state, flipscreen_w))
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
 MACHINE_CONFIG_END
 
 static MACHINE_CONFIG_DERIVED( shootouk, shootouj )
 	/* the Korean 'bootleg' has the usual DECO222 style encryption */
 	MCFG_DEVICE_REMOVE("maincpu")
-	MCFG_CPU_ADD("maincpu", DECO_222, 2000000)  /* 2 MHz? */
+	MCFG_CPU_ADD("maincpu", DECO_222, XTAL_12MHz / 6) // 2 MHz? (Assuming the same XTAL as DE-0219 pcb)
 	MCFG_CPU_PROGRAM_MAP(shootouj_map)
 MACHINE_CONFIG_END
 
 
 
 ROM_START( shootout )
-	ROM_REGION( 2*0x20000, "maincpu", 0 )   /* 128k for code + 128k for decrypted opcodes */
-	ROM_LOAD( "cu00.b1",        0x08000, 0x8000, CRC(090edeb6) SHA1(ab849d123dacf3947b1ebd29b70a20e066911a60) ) /* opcodes encrypted */
-	/* banked at 0x4000-0x8000 */
-	ROM_LOAD( "cu02.c3",        0x10000, 0x8000, CRC(2a913730) SHA1(584488278d58c4d34a2eebeaf39518f87cf5eecd) ) /* opcodes encrypted */
-	ROM_LOAD( "cu01.c1",        0x18000, 0x4000, CRC(8843c3ae) SHA1(c58ed4acac566f890cadf62bcbcced07a59243fc) ) /* opcodes encrypted */
+	ROM_REGION( 2 * 0x14000, "maincpu", 0 ) // 80k for code + 80k for decrypted opcodes
+	ROM_LOAD( "cu00.b1",        0x00000, 0x8000, CRC(090edeb6) SHA1(ab849d123dacf3947b1ebd29b70a20e066911a60) ) /* opcodes encrypted */
+	ROM_LOAD( "cu02.c3",        0x08000, 0x8000, CRC(2a913730) SHA1(584488278d58c4d34a2eebeaf39518f87cf5eecd) ) /* opcodes encrypted */
+	ROM_LOAD( "cu01.c1",        0x10000, 0x4000, CRC(8843c3ae) SHA1(c58ed4acac566f890cadf62bcbcced07a59243fc) ) /* opcodes encrypted */
 
-	ROM_REGION( 0x10000, "audiocpu", 0 )
-	ROM_LOAD( "cu09.j1",        0x0c000, 0x4000, CRC(c4cbd558) SHA1(0e940ae99febc1161e5f35550aa75afca88cb5e9) ) /* Sound CPU */
+	ROM_REGION( 0x4000, "audiocpu", 0 )
+	ROM_LOAD( "cu09.j1",        0x00000, 0x4000, CRC(c4cbd558) SHA1(0e940ae99febc1161e5f35550aa75afca88cb5e9) ) /* Sound CPU */
 
 	ROM_REGION( 0x04000, "gfx1", 0 )
 	ROM_LOAD( "cu11.h19",       0x00000, 0x4000, CRC(eff00460) SHA1(15daaa3d3125a981a26f31d43283faa5be26e96b) ) /* foreground characters */
@@ -339,10 +375,10 @@ ROM_START( shootout )
 ROM_END
 
 ROM_START( shootoutj )
-	ROM_REGION( 0x20000, "maincpu", 0 ) /* 128k for code  */
-	ROM_LOAD( "cg02.bin",    0x08000, 0x8000, CRC(8fc5d632) SHA1(809ac4eba09972229fe741c96fa8036d7139b6a8) )
-	ROM_LOAD( "cg00.bin",    0x10000, 0x8000, CRC(ef6ced1e) SHA1(feea508c7a60fc6cde1efee52cba628accd26028) )
-	ROM_LOAD( "cg01.bin",    0x18000, 0x4000, CRC(74cf11ca) SHA1(59edbc4633cd560e7b928b33e4c42d0125332a1b) )
+	ROM_REGION( 0x14000, "maincpu", 0 ) // 80k for code
+	ROM_LOAD( "cg02.bin",    0x00000, 0x8000, CRC(8fc5d632) SHA1(809ac4eba09972229fe741c96fa8036d7139b6a8) )
+	ROM_LOAD( "cg00.bin",    0x08000, 0x8000, CRC(ef6ced1e) SHA1(feea508c7a60fc6cde1efee52cba628accd26028) )
+	ROM_LOAD( "cg01.bin",    0x10000, 0x4000, CRC(74cf11ca) SHA1(59edbc4633cd560e7b928b33e4c42d0125332a1b) )
 
 	ROM_REGION( 0x04000, "gfx1", 0 )
 	ROM_LOAD( "cu11.h19",       0x00000, 0x4000, CRC(eff00460) SHA1(15daaa3d3125a981a26f31d43283faa5be26e96b) ) /* foreground characters */
@@ -364,10 +400,10 @@ ROM_START( shootoutj )
 ROM_END
 
 ROM_START( shootoutb )
-	ROM_REGION( 2*0x20000, "maincpu", 0 )   /* 128k for code + 128k for decrypted opcodes */
-	ROM_LOAD( "shootout.006", 0x08000, 0x8000, CRC(2c054888) SHA1(cb0de2f7d743506789626304e6bcbbc292fbe8bc) )
-	ROM_LOAD( "shootout.008", 0x10000, 0x8000, CRC(9651b656) SHA1(e90eddf2833ef36fa73b7b8d81d28443d2f60220) )
-	ROM_LOAD( "cg01.bin",     0x18000, 0x4000, CRC(74cf11ca) SHA1(59edbc4633cd560e7b928b33e4c42d0125332a1b) )
+	ROM_REGION( 2 * 0x14000, "maincpu", 0 ) // 80k for code + 80k for decrypted opcodes
+	ROM_LOAD( "shootout.006", 0x00000, 0x8000, CRC(2c054888) SHA1(cb0de2f7d743506789626304e6bcbbc292fbe8bc) )
+	ROM_LOAD( "shootout.008", 0x08000, 0x8000, CRC(9651b656) SHA1(e90eddf2833ef36fa73b7b8d81d28443d2f60220) )
+	ROM_LOAD( "cg01.bin",     0x10000, 0x4000, CRC(74cf11ca) SHA1(59edbc4633cd560e7b928b33e4c42d0125332a1b) )
 
 	ROM_REGION( 0x04000, "gfx1", 0 )
 	ROM_LOAD( "cu11.h19",       0x00000, 0x4000, CRC(eff00460) SHA1(15daaa3d3125a981a26f31d43283faa5be26e96b) ) /* foreground characters */
@@ -392,10 +428,10 @@ ROM_END
 
 DRIVER_INIT_MEMBER(shootout_state,shootout)
 {
-	membank("bank1")->configure_entries(0, 16, memregion("maincpu")->base() + 0x10000, 0x4000);
+	membank("bank1")->configure_entries(0, 16, memregion("maincpu")->base() + 0x8000, 0x4000);
 }
 
 
-GAME( 1985, shootout,  0,        shootout, shootout, shootout_state, shootout, ROT0, "Data East USA", "Shoot Out (US)", MACHINE_SUPPORTS_SAVE )
-GAME( 1985, shootoutj, shootout, shootouj, shootouj, shootout_state, shootout, ROT0, "Data East Corporation", "Shoot Out (Japan)", MACHINE_SUPPORTS_SAVE )
-GAME( 1985, shootoutb, shootout, shootouk, shootout, shootout_state, shootout, ROT0, "bootleg", "Shoot Out (Korean Bootleg)", MACHINE_SUPPORTS_SAVE )
+GAME( 1985, shootout,  0,        shootout, shootout, shootout_state, shootout, ROT0, "Data East USA",         "Shoot Out (US)",             MACHINE_SUPPORTS_SAVE )
+GAME( 1985, shootoutj, shootout, shootouj, shootouj, shootout_state, shootout, ROT0, "Data East Corporation", "Shoot Out (Japan)",          MACHINE_SUPPORTS_SAVE )
+GAME( 1985, shootoutb, shootout, shootouk, shootout, shootout_state, shootout, ROT0, "bootleg",               "Shoot Out (Korean Bootleg)", MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/drivers/sidepckt.cpp b/src/mame/drivers/sidepckt.cpp
index 03d362f..1530e0b 100644
--- a/src/mame/drivers/sidepckt.cpp
+++ b/src/mame/drivers/sidepckt.cpp
@@ -15,7 +15,7 @@ i8751 protection simulation and other fixes by Bryan McPhail, 15/10/00.
 
 
 ToDo:
- support screen flipping for sprites
+- sidepcktj: Intermission screen's background for player 2 is completely screwed (Maybe wrong/missing I8751 simulation for "cocktail mode" ?)
 
 
 Stephh's notes (based on the games M6809 code and some tests) :
@@ -123,6 +123,12 @@ Stephh's notes (based on the games M6809 code and some tests) :
       * Lives settings (table at 0x4696) : 06 03 02 instead of 06 03 09
       * Timer settings (table at 0x9d99) : 30 20 18 instead of 40 30 20, so the timer is faster
 
+Additional notes:
+----------------
+- sidepckt and sidepcktb don't have cocktail mode at all, while sidepcktj has a 'cooperative' cocktail mode; when it's the p2 turn,
+  the screen scrolls and a 'flipped score area' is shown on the other side, so the 2nd player just continues the same game.
+  Note that the screen never flips in any case.
+
 ***************************************************************************/
 
 #include "emu.h"
@@ -195,18 +201,16 @@ WRITE8_MEMBER(sidepckt_state::i8751_w)
 
 static ADDRESS_MAP_START( sidepckt_map, AS_PROGRAM, 8, sidepckt_state )
 	AM_RANGE(0x0000, 0x0fff) AM_RAM
-	AM_RANGE(0x1000, 0x13ff) AM_RAM_WRITE(videoram_w) AM_SHARE("videoram")
-	AM_RANGE(0x1400, 0x17ff) AM_RAM // ???
-	AM_RANGE(0x1800, 0x1bff) AM_RAM_WRITE(colorram_w) AM_SHARE("colorram")
-	AM_RANGE(0x1c00, 0x1fff) AM_RAM // ???
+	AM_RANGE(0x1000, 0x13ff) AM_MIRROR(0x400) AM_RAM_WRITE(videoram_w) AM_SHARE("videoram")
+	AM_RANGE(0x1800, 0x1bff) AM_MIRROR(0x400) AM_RAM_WRITE(colorram_w) AM_SHARE("colorram")
 	AM_RANGE(0x2000, 0x20ff) AM_RAM AM_SHARE("spriteram")
-	AM_RANGE(0x2100, 0x24ff) AM_RAM // ???
+	AM_RANGE(0x2100, 0x24ff) AM_WRITENOP // ??? (Unused spriteram? The game writes some values at boot, but never read)
 	AM_RANGE(0x3000, 0x3000) AM_READ_PORT("P1")
 	AM_RANGE(0x3001, 0x3001) AM_READ_PORT("P2")
 	AM_RANGE(0x3002, 0x3002) AM_READ_PORT("DSW1")
 	AM_RANGE(0x3003, 0x3003) AM_READ_PORT("DSW2")
 	AM_RANGE(0x3004, 0x3004) AM_WRITE(sound_cpu_command_w)
-	AM_RANGE(0x300c, 0x300c) AM_READNOP AM_WRITE(flipscreen_w)
+	AM_RANGE(0x300c, 0x300c) AM_READWRITE(scroll_y_r, scroll_y_w)
 	AM_RANGE(0x3014, 0x3014) AM_READ(i8751_r)
 	AM_RANGE(0x3018, 0x3018) AM_WRITE(i8751_w)
 	AM_RANGE(0x4000, 0xffff) AM_ROM
@@ -356,11 +360,12 @@ GFXDECODE_END
 
 void sidepckt_state::machine_reset()
 {
-	m_i8751_return = 0;
-	m_current_ptr = 0;
+	m_i8751_return  = 0;
+	m_current_ptr   = 0;
 	m_current_table = 0;
-	m_in_math = 0;
-	m_math_param = 0;
+	m_in_math       = 0;
+	m_math_param    = 0;
+	m_scroll_y      = 0;
 }
 
 static MACHINE_CONFIG_START( sidepckt, sidepckt_state )
@@ -498,6 +503,7 @@ DRIVER_INIT_MEMBER(sidepckt_state,sidepckt)
 	save_item(NAME(m_current_table));
 	save_item(NAME(m_in_math));
 	save_item(NAME(m_math_param));
+	save_item(NAME(m_scroll_y));
 }
 
 DRIVER_INIT_MEMBER(sidepckt_state,sidepcktj)
@@ -511,9 +517,10 @@ DRIVER_INIT_MEMBER(sidepckt_state,sidepcktj)
 	save_item(NAME(m_current_table));
 	save_item(NAME(m_in_math));
 	save_item(NAME(m_math_param));
+	save_item(NAME(m_scroll_y));
 }
 
 
-GAME( 1986, sidepckt,  0,        sidepckt,  sidepckt,  sidepckt_state, sidepckt,  ROT0, "Data East Corporation", "Side Pocket (World)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE )
-GAME( 1986, sidepcktj, sidepckt, sidepckt,  sidepcktj, sidepckt_state, sidepcktj, ROT0, "Data East Corporation", "Side Pocket (Japan)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE )
-GAME( 1986, sidepcktb, sidepckt, sidepcktb, sidepcktb, driver_device,  0,         ROT0, "bootleg", "Side Pocket (bootleg)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE )
+GAME( 1986, sidepckt,  0,        sidepckt,  sidepckt,  sidepckt_state, sidepckt,  ROT0, "Data East Corporation", "Side Pocket (World)",   MACHINE_SUPPORTS_SAVE )
+GAME( 1986, sidepcktj, sidepckt, sidepckt,  sidepcktj, sidepckt_state, sidepcktj, ROT0, "Data East Corporation", "Side Pocket (Japan)",   MACHINE_SUPPORTS_SAVE )
+GAME( 1986, sidepcktb, sidepckt, sidepcktb, sidepcktb, driver_device,  0,         ROT0, "bootleg",               "Side Pocket (bootleg)", MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/drivers/sigmab52.cpp b/src/mame/drivers/sigmab52.cpp
index 561e467..9bee645 100644
--- a/src/mame/drivers/sigmab52.cpp
+++ b/src/mame/drivers/sigmab52.cpp
@@ -582,12 +582,10 @@ static MACHINE_CONFIG_START( jwildb52, sigmab52_state )
 	MCFG_CPU_ADD("audiocpu", M6809, MAIN_CLOCK/9)   /* 2 MHz */
 	MCFG_CPU_PROGRAM_MAP(sound_prog_map)
 
-	MCFG_DEVICE_ADD("6840ptm_1", PTM6840, 0)
-	MCFG_PTM6840_INTERNAL_CLOCK(MAIN_CLOCK/9)       // FIXME
+	MCFG_DEVICE_ADD("6840ptm_1", PTM6840, MAIN_CLOCK/9) // FIXME
 	MCFG_PTM6840_IRQ_CB(INPUTLINE("maincpu", M6809_IRQ_LINE))
 
-	MCFG_DEVICE_ADD("6840ptm_2", PTM6840, 0)
-	MCFG_PTM6840_INTERNAL_CLOCK(MAIN_CLOCK/18)      // FIXME
+	MCFG_DEVICE_ADD("6840ptm_2", PTM6840, MAIN_CLOCK/18) // FIXME
 	MCFG_PTM6840_IRQ_CB(WRITELINE(sigmab52_state, ptm2_irq))
 
 	MCFG_NVRAM_ADD_NO_FILL("nvram")
diff --git a/src/mame/drivers/simple_st0016.cpp b/src/mame/drivers/simple_st0016.cpp
index 87ec5f3..2689a1f 100644
--- a/src/mame/drivers/simple_st0016.cpp
+++ b/src/mame/drivers/simple_st0016.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /*******************************************
 
diff --git a/src/mame/drivers/skyarmy.cpp b/src/mame/drivers/skyarmy.cpp
index 79d57eb..1494ee5 100644
--- a/src/mame/drivers/skyarmy.cpp
+++ b/src/mame/drivers/skyarmy.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina,Ryan Holtz
 /*
  2010.04.05. stephh
diff --git a/src/mame/drivers/slapfght.cpp b/src/mame/drivers/slapfght.cpp
index 633fa0d..6552059 100644
--- a/src/mame/drivers/slapfght.cpp
+++ b/src/mame/drivers/slapfght.cpp
@@ -481,39 +481,6 @@ ADDRESS_MAP_END
 
 
 
-/***************************************************************************
-
-  MCU Memory Maps
-
-  NOTE: handlers and simulation are in the src/mame/machine folder
-
-***************************************************************************/
-
-static ADDRESS_MAP_START( tigerh_m68705_map, AS_PROGRAM, 8, slapfght_state )
-	ADDRESS_MAP_GLOBAL_MASK(0x7ff)
-	AM_RANGE(0x0000, 0x0000) AM_READWRITE(tigerh_68705_portA_r, tigerh_68705_portA_w)
-	AM_RANGE(0x0001, 0x0001) AM_READWRITE(tigerh_68705_portB_r, tigerh_68705_portB_w)
-	AM_RANGE(0x0002, 0x0002) AM_READWRITE(tigerh_68705_portC_r, tigerh_68705_portC_w)
-	AM_RANGE(0x0004, 0x0004) AM_WRITE(tigerh_68705_ddrA_w)
-	AM_RANGE(0x0005, 0x0005) AM_WRITE(tigerh_68705_ddrB_w)
-	AM_RANGE(0x0006, 0x0006) AM_WRITE(tigerh_68705_ddrC_w)
-	AM_RANGE(0x0010, 0x007f) AM_RAM
-	AM_RANGE(0x0080, 0x07ff) AM_ROM
-ADDRESS_MAP_END
-
-static ADDRESS_MAP_START( slapfight_m68705_map, AS_PROGRAM, 8, slapfght_state )
-	ADDRESS_MAP_GLOBAL_MASK(0x7ff)
-	AM_RANGE(0x0000, 0x0000) AM_READWRITE(slapfight_68705_portA_r, slapfight_68705_portA_w)
-	AM_RANGE(0x0001, 0x0001) AM_READWRITE(slapfight_68705_portB_r, slapfight_68705_portB_w)
-	AM_RANGE(0x0002, 0x0002) AM_READWRITE(slapfight_68705_portC_r, slapfight_68705_portC_w)
-	AM_RANGE(0x0004, 0x0004) AM_WRITE(slapfight_68705_ddrA_w)
-	AM_RANGE(0x0005, 0x0005) AM_WRITE(slapfight_68705_ddrB_w)
-	AM_RANGE(0x0006, 0x0006) AM_WRITE(slapfight_68705_ddrC_w)
-	AM_RANGE(0x0010, 0x007f) AM_RAM
-	AM_RANGE(0x0080, 0x07ff) AM_ROM
-ADDRESS_MAP_END
-
-
 
 /***************************************************************************
 
@@ -770,15 +737,9 @@ void slapfght_state::machine_start()
 	m_main_sent = false;
 	m_from_main = 0;
 	m_from_mcu = 0;
-	m_portA_in = 0;
-	m_portA_out = 0;
-	m_ddrA = 0;
-	m_portB_in = 0;
-	m_portB_out = 0;
-	m_ddrB = 0;
-	m_portC_in = 0;
-	m_portC_out = 0;
-	m_ddrC = 0;
+	m_from_mcu_latch = 0;
+	m_to_mcu_latch = 0;
+	m_old_portB = 0;
 
 	m_getstar_status = 0;
 	m_getstar_sequence_index = 0;
@@ -801,15 +762,10 @@ void slapfght_state::machine_start()
 	save_item(NAME(m_main_sent));
 	save_item(NAME(m_from_main));
 	save_item(NAME(m_from_mcu));
-	save_item(NAME(m_portA_in));
-	save_item(NAME(m_portA_out));
-	save_item(NAME(m_ddrA));
-	save_item(NAME(m_portB_in));
-	save_item(NAME(m_portB_out));
-	save_item(NAME(m_ddrB));
-	save_item(NAME(m_portC_in));
-	save_item(NAME(m_portC_out));
-	save_item(NAME(m_ddrC));
+
+	save_item(NAME(m_from_mcu_latch));
+	save_item(NAME(m_to_mcu_latch));
+	save_item(NAME(m_old_portB));
 
 	save_item(NAME(m_getstar_status));
 	save_item(NAME(m_getstar_sequence_index));
@@ -1030,8 +986,13 @@ static MACHINE_CONFIG_START( tigerh, slapfght_state )
 	MCFG_CPU_PROGRAM_MAP(tigerh_sound_map)
 	MCFG_CPU_PERIODIC_INT_DRIVER(slapfght_state, sound_nmi, 360) // music speed, verified with pcb recording
 
-	MCFG_CPU_ADD("mcu", M68705, XTAL_36MHz/12) // 3MHz
-	MCFG_CPU_PROGRAM_MAP(tigerh_m68705_map)
+	MCFG_CPU_ADD("mcu", M68705_NEW, XTAL_36MHz/12) // 3MHz
+	MCFG_M68705_PORTA_R_CB(READ8(slapfght_state, tigerh_mcu_porta_r))
+	MCFG_M68705_PORTA_W_CB(WRITE8(slapfght_state, tigerh_mcu_porta_w))
+	MCFG_M68705_PORTB_W_CB(WRITE8(slapfght_state, tigerh_mcu_portb_w))
+	MCFG_M68705_PORTC_R_CB(READ8(slapfght_state, tigerh_mcu_portc_r))
+
+
 
 	MCFG_QUANTUM_PERFECT_CPU("maincpu")
 
@@ -1095,8 +1056,11 @@ static MACHINE_CONFIG_START( slapfigh, slapfght_state )
 	MCFG_CPU_PROGRAM_MAP(tigerh_sound_map)
 	MCFG_CPU_PERIODIC_INT_DRIVER(slapfght_state, sound_nmi, 180)
 
-	MCFG_CPU_ADD("mcu", M68705, XTAL_36MHz/12) // 3MHz
-	MCFG_CPU_PROGRAM_MAP(slapfight_m68705_map)
+	MCFG_CPU_ADD("mcu", M68705_NEW, XTAL_36MHz/12) // 3MHz
+	MCFG_M68705_PORTA_R_CB(READ8(slapfght_state, tigerh_mcu_porta_r))
+	MCFG_M68705_PORTA_W_CB(WRITE8(slapfght_state, tigerh_mcu_porta_w))
+	MCFG_M68705_PORTB_W_CB(WRITE8(slapfght_state, slapfght_mcu_portb_w))
+	MCFG_M68705_PORTC_R_CB(READ8(slapfght_state, slapfght_mcu_portc_r))
 
 	MCFG_QUANTUM_PERFECT_CPU("maincpu")
 
diff --git a/src/mame/drivers/sliver.cpp b/src/mame/drivers/sliver.cpp
index 4a32ce3..69e7f03 100644
--- a/src/mame/drivers/sliver.cpp
+++ b/src/mame/drivers/sliver.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /*
 Sliver - Hollow Corp.1996
diff --git a/src/mame/drivers/snesb.cpp b/src/mame/drivers/snesb.cpp
index 78b3d78..0010ac0 100644
--- a/src/mame/drivers/snesb.cpp
+++ b/src/mame/drivers/snesb.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina, Peter Ferrie,Stephane Humbert
 /***************************************************************************
 
diff --git a/src/mame/drivers/sothello.cpp b/src/mame/drivers/sothello.cpp
index 58d91f6..6c53747 100644
--- a/src/mame/drivers/sothello.cpp
+++ b/src/mame/drivers/sothello.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /*
  Super Othello (c)1986 Fujiwara/Success
diff --git a/src/mame/drivers/spbactn.cpp b/src/mame/drivers/spbactn.cpp
index 4ba2a0a..c3494b3 100644
--- a/src/mame/drivers/spbactn.cpp
+++ b/src/mame/drivers/spbactn.cpp
@@ -432,7 +432,7 @@ static MACHINE_CONFIG_START( spbactn, spbactn_state )
 	MCFG_TECMO_MIXER_SHIFTS(8,10,4)
 	MCFG_TECMO_MIXER_BLENDCOLS(   0x0000 + 0x300, 0x0000 + 0x200, 0x0000 + 0x100, 0x0000 + 0x000 )
 	MCFG_TECMO_MIXER_REGULARCOLS( 0x0800 + 0x300, 0x0800 + 0x200, 0x0800 + 0x100, 0x0800 + 0x000 )
-	MCFG_TECMO_MIXER_BLENDSOUCE( 0x1000 + 0x000, 0x1000 + 0x100)
+	MCFG_TECMO_MIXER_BLENDSOURCE( 0x1000 + 0x000, 0x1000 + 0x100)
 	MCFG_TECMO_MIXER_BGPEN(0x800 + 0x300)
 
 	/* sound hardware */
@@ -485,7 +485,7 @@ static MACHINE_CONFIG_START( spbactnp, spbactn_state )
 	MCFG_TECMO_MIXER_SHIFTS(12,14,8)
 	MCFG_TECMO_MIXER_BLENDCOLS(   0x0000 + 0x300, 0x0000 + 0x200, 0x0000 + 0x100, 0x0000 + 0x000 )
 	MCFG_TECMO_MIXER_REGULARCOLS( 0x0800 + 0x300, 0x0800 + 0x200, 0x0800 + 0x100, 0x0800 + 0x000 )
-	MCFG_TECMO_MIXER_BLENDSOUCE( 0x1000 + 0x000, 0x1000 + 0x100)
+	MCFG_TECMO_MIXER_BLENDSOURCE( 0x1000 + 0x000, 0x1000 + 0x100)
 	MCFG_TECMO_MIXER_BGPEN(0x800 + 0x300)
 
 	/* sound hardware  - different? */
diff --git a/src/mame/drivers/speglsht.cpp b/src/mame/drivers/speglsht.cpp
index 91c1a3e..a625bde 100644
--- a/src/mame/drivers/speglsht.cpp
+++ b/src/mame/drivers/speglsht.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /*
 Super Eagle Shot
diff --git a/src/mame/drivers/spinb.cpp b/src/mame/drivers/spinb.cpp
index 569c10e..806c8e9 100644
--- a/src/mame/drivers/spinb.cpp
+++ b/src/mame/drivers/spinb.cpp
@@ -36,6 +36,7 @@ ToDo:
 #include "machine/i8255.h"
 #include "sound/msm5205.h"
 #include "machine/7474.h"
+#include "machine/74157.h"
 
 class spinb_state : public genpin_class
 {
@@ -50,6 +51,8 @@ public:
 		, m_msm_m(*this, "msm_m")
 		, m_ic5a(*this, "ic5a")
 		, m_ic5m(*this, "ic5m")
+		, m_ic14a(*this, "ic14a")
+		, m_ic14m(*this, "ic14m")
 		, m_switches(*this, "SW.%u", 0)
 	{ }
 
@@ -110,6 +113,8 @@ private:
 	uint8_t *m_p_dmdcpu;
 	virtual void machine_reset() override;
 	virtual void machine_start() override;
+	void update_sound_a();
+	void update_sound_m();
 	required_device<cpu_device> m_maincpu;
 	required_device<cpu_device> m_audiocpu;
 	required_device<cpu_device> m_musiccpu;
@@ -118,6 +123,8 @@ private:
 	required_device<msm5205_device> m_msm_m;
 	required_device<ttl7474_device> m_ic5a;
 	required_device<ttl7474_device> m_ic5m;
+	required_device<hct157_device> m_ic14a;
+	required_device<hct157_device> m_ic14m;
 	required_ioport_array<11> m_switches;
 };
 
@@ -407,6 +414,8 @@ WRITE8_MEMBER( spinb_state::sndbank_a_w )
 		m_sound_addr_a |= (2<<19);
 	else if (BIT(data, 7))
 		m_sndbank_a = 0xff;
+
+	update_sound_a();
 }
 
 WRITE8_MEMBER( spinb_state::sndbank_m_w )
@@ -420,50 +429,50 @@ WRITE8_MEMBER( spinb_state::sndbank_m_w )
 		m_sound_addr_m |= (2<<19);
 	else if (BIT(data, 7))
 		m_sndbank_m = 0xff;
+
+	update_sound_m();
 }
 
 WRITE_LINE_MEMBER( spinb_state::vck_a_w )
 {
 	m_ic5a->clock_w(0);
 	m_ic5a->clock_w(1);
+}
 
+void spinb_state::update_sound_a()
+{
 	if (m_sndbank_a != 0xff)
-	{
-		if (!m_pc0a)
-			m_msm_a->data_w(m_p_audio[m_sound_addr_a] & 15);
-		else
-			m_msm_a->data_w(m_p_audio[m_sound_addr_a] >> 4);
-	}
+		m_ic14a->ab_w(m_p_audio[m_sound_addr_a]);
 	else
-		m_msm_a->data_w(0);
+		m_ic14a->ab_w(0);
 }
 
 WRITE_LINE_MEMBER( spinb_state::vck_m_w )
 {
 	m_ic5m->clock_w(0);
 	m_ic5m->clock_w(1);
+}
 
+void spinb_state::update_sound_m()
+{
 	if (m_sndbank_m != 0xff)
-	{
-		if (!m_pc0m)
-			m_msm_m->data_w(m_p_music[m_sound_addr_m] & 15);
-		else
-			m_msm_m->data_w(m_p_music[m_sound_addr_m] >> 4);
-	}
+		m_ic14m->ab_w(m_p_music[m_sound_addr_m]);
 	else
-		m_msm_m->data_w(0);
+		m_ic14m->ab_w(0);
 }
 
 WRITE_LINE_MEMBER( spinb_state::ic5a_w )
 {
 	m_pc0a = state;
 	m_ic5a->d_w(state);
+	m_ic14a->select_w(state);
 }
 
 WRITE_LINE_MEMBER( spinb_state::ic5m_w )
 {
 	m_pc0m = state;
 	m_ic5m->d_w(state);
+	m_ic14m->select_w(state);
 }
 
 READ8_MEMBER( spinb_state::ppia_c_r )
@@ -479,21 +488,25 @@ READ8_MEMBER( spinb_state::ppim_c_r )
 WRITE8_MEMBER( spinb_state::ppia_b_w )
 {
 	m_sound_addr_a = (m_sound_addr_a & 0xffff00) | data;
+	update_sound_a();
 }
 
 WRITE8_MEMBER( spinb_state::ppim_b_w )
 {
 	m_sound_addr_m = (m_sound_addr_m & 0xffff00) | data;
+	update_sound_m();
 }
 
 WRITE8_MEMBER( spinb_state::ppia_a_w )
 {
 	m_sound_addr_a = (m_sound_addr_a & 0xff00ff) | (data << 8);
+	update_sound_a();
 }
 
 WRITE8_MEMBER( spinb_state::ppim_a_w )
 {
 	m_sound_addr_m = (m_sound_addr_m & 0xff00ff) | (data << 8);
+	update_sound_m();
 }
 
 WRITE8_MEMBER( spinb_state::ppia_c_w )
@@ -523,6 +536,8 @@ void spinb_state::machine_reset()
 	m_sndbank_a = 0xff;
 	m_sndbank_m = 0xff;
 	m_row = 0;
+	update_sound_a();
+	update_sound_m();
 }
 
 void spinb_state::machine_start()
@@ -703,8 +718,14 @@ static MACHINE_CONFIG_START( spinb, spinb_state )
 	MCFG_DEVICE_ADD("ic5a", TTL7474, 0)
 	MCFG_7474_COMP_OUTPUT_CB(WRITELINE(spinb_state, ic5a_w))
 
+	MCFG_DEVICE_ADD("ic14a", HCT157, 0)
+	MCFG_74157_OUT_CB(DEVWRITE8("msm_a", msm5205_device, data_w))
+
 	MCFG_DEVICE_ADD("ic5m", TTL7474, 0)
 	MCFG_7474_COMP_OUTPUT_CB(WRITELINE(spinb_state, ic5m_w))
+
+	MCFG_DEVICE_ADD("ic14m", HCT157, 0)
+	MCFG_74157_OUT_CB(DEVWRITE8("msm_m", msm5205_device, data_w))
 MACHINE_CONFIG_END
 
 static MACHINE_CONFIG_DERIVED( vrnwrld, spinb )
diff --git a/src/mame/drivers/srmp2.cpp b/src/mame/drivers/srmp2.cpp
index dc6e15c..55108fc 100644
--- a/src/mame/drivers/srmp2.cpp
+++ b/src/mame/drivers/srmp2.cpp
@@ -196,7 +196,7 @@ WRITE16_MEMBER(srmp2_state::mjyuugi_adpcm_bank_w)
 }
 
 
-WRITE16_MEMBER(srmp2_state::srmp2_adpcm_code_w)
+WRITE8_MEMBER(srmp2_state::adpcm_code_w)
 {
 /*
     - Received data may be playing ADPCM number.
@@ -214,28 +214,7 @@ WRITE16_MEMBER(srmp2_state::srmp2_adpcm_code_w)
 	m_adpcm_sptr += (m_adpcm_bank * 0x10000);
 	m_adpcm_eptr += (m_adpcm_bank * 0x10000);
 
-	m_msm->reset_w(0);
-	m_adpcm_data = -1;
-}
-
-
-WRITE8_MEMBER(srmp2_state::srmp3_adpcm_code_w)
-{
-/*
-    - Received data may be playing ADPCM number.
-    - 0x000000 - 0x0000ff and 0x010000 - 0x0100ff are offset table.
-    - When the hardware receives the ADPCM number, it refers the offset
-      table and plays the ADPCM for itself.
-*/
-
-	uint8_t *ROM = memregion("adpcm")->base();
-
-	m_adpcm_sptr = (ROM[((m_adpcm_bank * 0x10000) + (data << 2) + 0)] << 8);
-	m_adpcm_eptr = (ROM[((m_adpcm_bank * 0x10000) + (data << 2) + 1)] << 8);
-	m_adpcm_eptr  = (m_adpcm_eptr - 1) & 0x0ffff;
-
-	m_adpcm_sptr += (m_adpcm_bank * 0x10000);
-	m_adpcm_eptr += (m_adpcm_bank * 0x10000);
+	//printf("%02x %08x %08x %08x\n",data,m_adpcm_sptr,m_adpcm_eptr,((m_adpcm_bank * 0x10000) + (data << 2) + 0));
 
 	m_msm->reset_w(0);
 	m_adpcm_data = -1;
@@ -419,7 +398,7 @@ static ADDRESS_MAP_START( srmp2_map, AS_PROGRAM, 16, srmp2_state )
 	AM_RANGE(0x900000, 0x900001) AM_WRITENOP                        /* ??? */
 	AM_RANGE(0xa00000, 0xa00001) AM_READWRITE8(iox_mux_r, iox_command_w,0x00ff) /* key matrix | I/O */
 	AM_RANGE(0xa00002, 0xa00003) AM_READWRITE8(iox_status_r,iox_data_w,0x00ff)
-	AM_RANGE(0xb00000, 0xb00001) AM_WRITE(srmp2_adpcm_code_w)   /* ADPCM number */
+	AM_RANGE(0xb00000, 0xb00001) AM_WRITE8(adpcm_code_w,0x00ff)   /* ADPCM number */
 	AM_RANGE(0xb00002, 0xb00003) AM_READ8(vox_status_r,0x00ff)      /* ADPCM voice status */
 	AM_RANGE(0xc00000, 0xc00001) AM_WRITE8(srmp2_irq2_ack_w,0x00ff)         /* irq ack lv 2 */
 	AM_RANGE(0xd00000, 0xd00001) AM_WRITE8(srmp2_irq4_ack_w,0x00ff)         /* irq ack lv 4 */
@@ -454,7 +433,7 @@ static ADDRESS_MAP_START( mjyuugi_map, AS_PROGRAM, 16, srmp2_state )
 	AM_RANGE(0x800000, 0x800001) AM_READNOP             /* ??? */
 	AM_RANGE(0x900000, 0x900001) AM_READWRITE8(iox_mux_r, iox_command_w,0x00ff) /* key matrix | I/O */
 	AM_RANGE(0x900002, 0x900003) AM_READWRITE8(iox_status_r,iox_data_w,0x00ff)
-	AM_RANGE(0xa00000, 0xa00001) AM_WRITE(srmp2_adpcm_code_w)           /* ADPCM number */
+	AM_RANGE(0xa00000, 0xa00001) AM_WRITE8(adpcm_code_w,0x00ff)           /* ADPCM number */
 	AM_RANGE(0xb00002, 0xb00003) AM_READ8(vox_status_r,0x00ff)      /* ADPCM voice status */
 	AM_RANGE(0xb00000, 0xb00001) AM_DEVREAD8("aysnd", ay8910_device, data_r, 0x00ff)
 	AM_RANGE(0xb00000, 0xb00003) AM_DEVWRITE8("aysnd", ay8910_device, address_data_w, 0x00ff)
@@ -503,7 +482,7 @@ static ADDRESS_MAP_START( srmp3_io_map, AS_IO, 8, srmp2_state )
 	AM_RANGE(0x20, 0x20) AM_WRITE(srmp3_irq_ack_w)                              /* interrupt acknowledge */
 	AM_RANGE(0x40, 0x40) AM_READ_PORT("SYSTEM") AM_WRITE(srmp3_flags_w)         /* coin, service | GFX bank, counter, lockout */
 	AM_RANGE(0x60, 0x60) AM_WRITE(srmp3_rombank_w)                              /* ROM bank select */
-	AM_RANGE(0xa0, 0xa0) AM_WRITE(srmp3_adpcm_code_w)                   /* ADPCM number */
+	AM_RANGE(0xa0, 0xa0) AM_WRITE(adpcm_code_w)                   /* ADPCM number */
 	AM_RANGE(0xa1, 0xa1) AM_READ(vox_status_r)                                  /* ADPCM voice status */
 	AM_RANGE(0xc0, 0xc0) AM_READWRITE(iox_mux_r, iox_command_w)                 /* key matrix | I/O */
 	AM_RANGE(0xc1, 0xc1) AM_READWRITE(iox_status_r,iox_data_w)
diff --git a/src/mame/drivers/srmp5.cpp b/src/mame/drivers/srmp5.cpp
index e9bb605..572da2a 100644
--- a/src/mame/drivers/srmp5.cpp
+++ b/src/mame/drivers/srmp5.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /*
 
diff --git a/src/mame/drivers/ssfindo.cpp b/src/mame/drivers/ssfindo.cpp
index 2a94dfe..7ea734f 100644
--- a/src/mame/drivers/ssfindo.cpp
+++ b/src/mame/drivers/ssfindo.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /************************************************************************
 
diff --git a/src/mame/drivers/ssingles.cpp b/src/mame/drivers/ssingles.cpp
index 7185169..89ed37d 100644
--- a/src/mame/drivers/ssingles.cpp
+++ b/src/mame/drivers/ssingles.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /*
  'Swinging Singles' US distribution by Ent. Ent. Ltd
diff --git a/src/mame/drivers/ssrj.cpp b/src/mame/drivers/ssrj.cpp
index 8857342..22e8c43 100644
--- a/src/mame/drivers/ssrj.cpp
+++ b/src/mame/drivers/ssrj.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /***********************************
  Super Speed Race Jr (c) 1985 Taito
diff --git a/src/mame/drivers/stv.cpp b/src/mame/drivers/stv.cpp
index c6ffc5e..1cffadd 100644
--- a/src/mame/drivers/stv.cpp
+++ b/src/mame/drivers/stv.cpp
@@ -53,6 +53,7 @@
 
 
 /*
+Sega 315-5649 IO IC, functional same as 315-5338A, also used in Model 2/3, integrated into 315-6146 'MIE' MCU, etc
 I/O overview:                   Connector (as described in service manual)
     PORT-A  1st player inputs   JAMMA (56P)
     PORT-B  2nd player inputs   JAMMA (56P)
@@ -75,17 +76,17 @@ offsets:
     0x0009 PORT-E (P3)
     0x000b PORT-F (P4 / Extra 6B layout)
     0x000d PORT-G
-    0x000f
-    0x0011 PORT_SEL?
+    0x000f unused
+    0x0011 PORT_DIRECTION (each bit configure above IO ports, 1 - input, 0 - output)
     ---x ---- joystick/mahjong panel select
     ---- x--- used in danchih (different mux scheme for the hanafuda panel?)
-    0x0013
-    0x0015 SERIAL COM Tx
-    0x0017
-    0x0019 SERIAL COM Rx
-    0x001b
-    0x001d <Technical Bowling>
-    0x001f PORT-AD
+    0x0013 RS422 TXD1
+    0x0015 RS422 TXD2 SERIAL COM Tx
+    0x0017 RS422 RXD1
+    0x0019 RS422 RXD2 SERIAL COM Rx
+    0x001b RS422 FLAG
+    0x001d MODE (bit 7 - set PORT-G to counter-mode, bits 0-5 - RS422 satellite mode and node#)  <Technical Bowling>
+    0x001f PORT-AD (8ch, write: bits 0-2 - set channel, read: channel data with autoinc channel number)
 */
 
 READ8_MEMBER(stv_state::stv_ioga_r)
@@ -103,7 +104,7 @@ READ8_MEMBER(stv_state::stv_ioga_r)
 		case 0x01: res = ioport("PORTA")->read(); break; // P1
 		case 0x03: res = ioport("PORTB")->read(); break; // P2
 		case 0x05: res = ioport("PORTC")->read(); break; // SYSTEM
-		case 0x07: res = m_system_output | 0xf0; break; // port D, read-backs value written
+		case 0x07: res = m_system_output; break; // port D, read-backs value written
 		case 0x09: res = ioport("PORTE")->read(); break; // P3
 		case 0x0b: res = ioport("PORTF")->read(); break; // P4
 		case 0x1b: res = 0; break; // Serial COM READ status
@@ -122,7 +123,7 @@ WRITE8_MEMBER(stv_state::stv_ioga_w)
 	switch(offset)
 	{
 		case 0x07:
-			m_system_output = data & 0xf;
+			m_system_output = data;
 			/*Why does the BIOS tests these as ACTIVE HIGH? A program bug?*/
 			machine().bookkeeping().coin_counter_w(0,~data & 0x01);
 			machine().bookkeeping().coin_counter_w(1,~data & 0x02);
@@ -201,7 +202,7 @@ READ8_MEMBER(stv_state::stvmp_ioga_r)
 	{
 		case 0x01:
 		case 0x03:
-			if(m_port_sel & 0x10) // joystick select
+			if(m_port_sel & 0x10) // joystick select <<< this is obviously wrong, this bit only select PORTE direction
 				res = stv_ioga_r(space,offset);
 			else // mahjong panel select
 			{
@@ -1783,7 +1784,7 @@ ROM_START( astrass )
 	ROM_LOAD16_WORD_SWAP( "mpr20832.8",     0x1c00000, 0x0400000, CRC(af1b0985) SHA1(d7a0e4e0a8b0556915f924bdde8c3d14e5b3423e) ) // good (was .18s)
 	ROM_LOAD16_WORD_SWAP( "mpr20833.9",     0x2000000, 0x0400000, CRC(cb6af231) SHA1(4a2e5d7c2fd6179c19cdefa84a03f9a34fbb9e70) ) // good (was .19s)
 
-	// 25349801    1998     317-5040-COM   ST-V      (yes, the 317-5040-COM chip was reused for 3 different games and on both Naomi and ST-V!)
+	// 610-0374-90   1998     317-5040-COM   ST-V      (yes, the 317-5040-COM chip was reused for 3 different games and on both Naomi and ST-V!)
 	ROM_PARAMETER( ":315_5881:key", "052e2901" )
 ROM_END
 
@@ -1930,7 +1931,7 @@ ROM_START( elandore )
 	ROM_LOAD16_WORD_SWAP( "mpr21306.1",    0x1800000, 0x0400000, CRC(87a5929c) SHA1(b259341d7b0e1fa98959bf52d23db5c308a8efdd) ) // good (was .17)
 	ROM_LOAD16_WORD_SWAP( "mpr21308.8",    0x1c00000, 0x0400000, CRC(336ec1a4) SHA1(20d1fce050cf6132d284b91853a4dd5626372ef0) ) // good (was .18s)
 
-	//             1998     317-5043-COM   ST-V
+	// 610-0374-126   1998     317-5043-COM   ST-V
 	ROM_PARAMETER( ":315_5881:key", "05226d41" )
 ROM_END
 
@@ -1946,7 +1947,7 @@ ROM_START( ffrevng10 )
 	ROM_LOAD16_WORD_SWAP( "mpr21877.6",   0x1400000, 0x0400000, CRC(c22a4a75) SHA1(3276bc0628e71b432f21ba9a4f5ff7ccc8769cd9) ) // good (was .16)
 	ROM_LOAD16_WORD_SWAP( "opr21878.1",   0x1800000, 0x0200000, CRC(2ea4a64d) SHA1(928a973dce5eba0a1628d61ba56a530de990a946) ) // good (was .17)
 
-	//             1998     317-5049-COM   ST-V
+	// 610-0374-128   1998     317-5049-COM   ST-V
 	ROM_PARAMETER( ":315_5881:key", "0524ac01" )
 ROM_END
 
@@ -1965,7 +1966,7 @@ ROM_START( ffreveng )
 	ROM_LOAD16_WORD_SWAP( "mpr21877.6",   0x1400000, 0x0400000, CRC(c22a4a75) SHA1(3276bc0628e71b432f21ba9a4f5ff7ccc8769cd9) ) // good (was .16)
 	ROM_LOAD16_WORD_SWAP( "opr21878.1",   0x1800000, 0x0200000, CRC(2ea4a64d) SHA1(928a973dce5eba0a1628d61ba56a530de990a946) ) // good (was .17)
 
-	//             1998     317-5049-COM   ST-V
+	// 610-0374-128   1998     317-5049-COM   ST-V
 	ROM_PARAMETER( ":315_5881:key", "0524ac01" )
 ROM_END
 
@@ -2224,7 +2225,7 @@ ROM_START( rsgun )
 	ROM_LOAD16_WORD_SWAP( "mpr20961.4",   0x0c00000, 0x0400000, CRC(0e06295c) SHA1(0ec2842622f3e9dc5689abd58aeddc7e5603b97a) ) // good (was .14)
 	ROM_LOAD16_WORD_SWAP( "mpr20962.5",   0x1000000, 0x0400000, CRC(f1e6c7fc) SHA1(0ba0972f1bc7c56f4e0589d3e363523cea988bb0) ) // good (was .15)
 
-	//             1998     317-5041-COM   ST-V
+	// 610-0374-96   1998     317-5041-COM   ST-V
 	ROM_PARAMETER( ":315_5881:key", "05272d01" )
 ROM_END
 
@@ -2415,7 +2416,7 @@ ROM_START( sss )
 	ROM_REGION16_BE( 0x80, "eeprom", 0 ) // preconfigured to 1 player
 	ROM_LOAD( "sss.nv", 0x0000, 0x0080, CRC(3473b2f3) SHA1(6480b4b321af8ee6e967710e74f2556c17bfca97) )
 
-	//             1998     317-5042-COM   ST-V
+	// 610-0374-107   1998     317-5042-COM   ST-V
 	ROM_PARAMETER( ":315_5881:key", "052b6901" )
 ROM_END
 
@@ -2448,7 +2449,7 @@ ROM_START( twcup98 )
 	ROM_LOAD16_WORD_SWAP( "mpr20823.14",    0x0c00000, 0x0400000, CRC(6e6d4e95) SHA1(c387d03ba27580c62ac0bf780915fdf41552df6f) ) // tested as IC4
 	ROM_LOAD16_WORD_SWAP( "mpr20824.15",    0x1000000, 0x0400000, CRC(4cf18a25) SHA1(310961a5f114fea8938a3f514dffd5231e910a5a) ) // tested as IC5
 
-	// 25209801    1998     317-5039-COM   ST-V
+	// 610-0374-89   1998     317-5039-COM   ST-V
 	ROM_PARAMETER( ":315_5881:key", "05200913" )
 ROM_END
 
@@ -2464,7 +2465,7 @@ ROM_START( twsoc98 )
 	ROM_LOAD16_WORD_SWAP( "mpr20823.14",    0x0c00000, 0x0400000, CRC(6e6d4e95) SHA1(c387d03ba27580c62ac0bf780915fdf41552df6f) ) // tested as IC4
 	ROM_LOAD16_WORD_SWAP( "mpr20824.15",    0x1000000, 0x0400000, CRC(4cf18a25) SHA1(310961a5f114fea8938a3f514dffd5231e910a5a) ) // tested as IC5
 
-	// 25209801    1998     317-5039-COM   ST-V
+	// 610-0374-91   1998     317-5039-COM   ST-V
 	ROM_PARAMETER( ":315_5881:key", "05200913" )
 ROM_END
 
@@ -2826,12 +2827,12 @@ ROM_START( choroqhr ) // set to 1p
 	STV_BIOS
 
 	ROM_REGION32_BE( 0x3000000, "cart", ROMREGION_ERASE00 ) /* SH2 code */
-	ROM_LOAD16_WORD_SWAP( "ic22.bin",     0x0200000, 0x200000, CRC(fd04598b) SHA1(4797127869fafae0ecfddc07b1c1325b11ca981a) )
+	ROM_LOAD16_WORD_SWAP( "ic22.bin",     0x0200000, 0x200000, CRC(22c58710) SHA1(6d8b849f6fcf6566193dcff6e2c7c857b7d0d9bf) )
 	ROM_LOAD16_WORD_SWAP( "ic24.bin",     0x0400000, 0x200000, CRC(09b8a154) SHA1(cfd212c6fe6188b9c665650b21f2fd80cd65268f) )
 	ROM_LOAD16_WORD_SWAP( "ic26.bin",     0x0600000, 0x200000, CRC(136ca5e9) SHA1(8697a415d0958e58f5cea5dcc767dd6a4cbdef5c) )
 	ROM_LOAD16_WORD_SWAP( "ic28.bin",     0x0800000, 0x200000, CRC(3c949563) SHA1(ab2a9f9ec23071cc236dee945b436a9cd73efb92) )
 	ROM_LOAD16_WORD_SWAP( "ic30.bin",     0x0a00000, 0x200000, CRC(7e93078d) SHA1(10fa99029a3e741ea0fddcf00ee07b5fd039bf19) )
-	ROM_LOAD16_WORD_SWAP( "ic32.bin",     0x0c00000, 0x200000, BAD_DUMP CRC(d311c5f6) SHA1(c210463ae5b4bcc498de786e05dec245c0d3b46e) ) // ic7 bad
+	ROM_LOAD16_WORD_SWAP( "ic32.bin",     0x0c00000, 0x200000, CRC(86cdcbd8) SHA1(90060cde84c75fd4146ebf6b9101f04140408e88) )
 	//ROM_LOAD16_WORD_SWAP( "ic32.bad2.bin", 0x000000, 0x200000, CRC(76709d73) SHA1(a7805e956ee1a3701a803d0af082c33c89c26c3a) )
 	//ROM_LOAD16_WORD_SWAP( "ic32.bad3.bin", 0x000000, 0x200000, CRC(b873cf3e) SHA1(8ed42a229e416125d7a2359faaea17208324feb0) )
 	//ROM_LOAD16_WORD_SWAP( "ic32.bad4.bin", 0x000000, 0x200000, CRC(ed808ad4) SHA1(b00791ec3ee6255bccde171279a1a14e322d0e6d) )
@@ -3023,11 +3024,11 @@ ROM_START( prc28su ) // set to 1p
 	ROM_LOAD16_WORD_SWAP( "u22.bin",    0x0200000, 0x0200000, CRC(b78cf122) SHA1(10ecdbb04d1ce2c7f98e57260bbd6a09b8a5905d) ) // OK (tested as IC7)
 	ROM_LOAD16_WORD_SWAP( "u24.bin",    0x0400000, 0x0200000, CRC(aca05d29) SHA1(68c487821a912aea867f2f5041f5d926f31e4513) ) // OK (tested as IC2)
 	ROM_LOAD16_WORD_SWAP( "u26.bin",    0x0600000, 0x0200000, CRC(5591f6e2) SHA1(95a28b0a4fc2aeb063902505a4f3613c33f9059a) ) // OK (tested as IC2)
-	ROM_LOAD16_WORD_SWAP( "u28.bin",    0x0800000, 0x0200000, BAD_DUMP CRC(0899889b) SHA1(e7a77350a2421bbd867681f4c256d3b0d473468d) ) // BAD? (tested as IC3)
-	ROM_LOAD16_WORD_SWAP( "u30.bin",    0x0a00000, 0x0200000, BAD_DUMP CRC(2156b889) SHA1(047d73156da503711283bf7ca8e13722c22d2e1e) ) // BAD? (tested as IC3)
-	ROM_LOAD16_WORD_SWAP( "u32.bin",    0x0c00000, 0x0200000, CRC(e989f1e3) SHA1(768ce36b515ef2d777d5ea0dc074d700ade56110) ) // not tested?!
-	ROM_LOAD16_WORD_SWAP( "u34.bin",    0x0e00000, 0x0200000, BAD_DUMP CRC(555863d3) SHA1(bce1e63af9c45d9bd99685a42e9b3a6c2af66c87) ) // not tested?!
-	ROM_LOAD16_WORD_SWAP( "u36.bin",    0x1000000, 0x0200000, CRC(7cb3cd89) SHA1(7f421b58cde211f047e91fd352c7f7c78f4b2555) ) // not tested?! ( FIXED BITS (xxxxxxxx11111111) )
+	ROM_LOAD16_WORD_SWAP( "u28.bin",    0x0800000, 0x0200000, CRC(0899889b) SHA1(e7a77350a2421bbd867681f4c256d3b0d473468d) ) // OK (tested as IC3)
+	ROM_LOAD16_WORD_SWAP( "u30.bin",    0x0a00000, 0x0200000, CRC(03b9eacf) SHA1(d69c10f7613d9f52042dd6cce64e74e2b1ecc2d8) ) // OK (tested as IC3)
+	ROM_LOAD16_WORD_SWAP( "u32.bin",    0x0c00000, 0x0200000, CRC(5dc1f4d7) SHA1(dbb04d4c45b3ecf5416f32e34d3cabd4945352fb) ) // OK
+	ROM_LOAD16_WORD_SWAP( "u34.bin",    0x0e00000, 0x0200000, CRC(0222734a) SHA1(d65311234100f81aa40a6738f79c61e598da8665) ) // OK
+	ROM_LOAD16_WORD_SWAP( "u36.bin",    0x1000000, 0x0200000, CRC(57c30e0f) SHA1(2286ba237edecc0cab1539b30b5f36843c7e276d) ) // OK
 
 	ROM_REGION16_BE( 0x80, "eeprom", 0 ) // preconfigured to 1 player
 	ROM_LOAD( "eeprom", 0x0000, 0x0080, CRC(447bb3bd) SHA1(9fefec09849bfa0c14b49e73ff13e2a538dff511) )
@@ -3061,11 +3062,12 @@ ROM_START( prc2ksu ) // set to 1p (this dump is too damaged to even run the ROM
 
 	ROM_REGION32_BE( 0x3000000, "cart", ROMREGION_ERASE00 ) /* SH2 code */
 
-	ROM_LOAD16_WORD_SWAP( "ic22.bin",    0x0200000, 0x0200000, BAD_DUMP CRC(455b22c3) SHA1(8eb87461b690783b36eaa8a56dd1fbeadfa0198d) ) // BAD
+	// NOTE: Game fails IC7 check, might be okay, might not be - supposedly ST-V print carts are known to have bad ROM tests(?)
+	ROM_LOAD16_WORD_SWAP( "ic22.bin",    0x0200000, 0x0200000, CRC(4b3de7df) SHA1(869c3840ac2eab263bb8b79ba1430e5789fa5758) )
 	ROM_LOAD16_WORD_SWAP( "ic24.bin",    0x0400000, 0x0200000, BAD_DUMP CRC(02da49b7) SHA1(dd19bfd6c21f432b3af011ce43ba38d295c06c6d) ) // (maybe bad, maybe good, consistent read at least)
 	ROM_LOAD16_WORD_SWAP( "ic26.bin",    0x0600000, 0x0200000, BAD_DUMP CRC(a431d614) SHA1(75de91d8eff5af7e1b668012a0613884ba660e21) ) // (maybe bad, maybe good, consistent read at least)
-	ROM_LOAD16_WORD_SWAP( "ic28.bin",    0x0800000, 0x0200000, BAD_DUMP CRC(07f99eeb) SHA1(d6798b8eba1c4d6993d9ec6a62c4e39fc58428f3) ) // BAD
-	ROM_LOAD16_WORD_SWAP( "ic30.bin",    0x0a00000, 0x0200000, BAD_DUMP CRC(91b261b1) SHA1(4c270d73be9a82e7139aafc9af5d89e0e4e0c80a) ) // BAD
+	ROM_LOAD16_WORD_SWAP( "ic28.bin",    0x0800000, 0x0200000, CRC(c0fba1a5) SHA1(5f98be1eed5f74e62fe5a3e33fdcf3b827dda1a7) )
+	ROM_LOAD16_WORD_SWAP( "ic30.bin",    0x0a00000, 0x0200000, CRC(0811d0e4) SHA1(b4fd9369c80f76141ae2fb38525b405b4c2f391a) )
 
 	ROM_REGION16_BE( 0x80, "eeprom", ROMREGION_ERASE00 ) // preconfigured to 1 player
 ROM_END
@@ -3387,7 +3389,7 @@ GAME( 1997, cotton2,   stvbios, stv,      stv, stv_state,        cotton2,    ROT
 GAME( 1998, cottonbm,  stvbios, stv,      stv, stv_state,        cottonbm,   ROT0,   "Success",                      "Cotton Boomerang (JUET 980709 V1.000)", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS )
 GAME( 1995, critcrsh,  stvbios, stv,      critcrsh, stv_state,   critcrsh,   ROT0,   "Sega",                         "Critter Crusher (EA 951204 V1.000)", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS )
 GAME( 1999, danchih,   stvbios, stv,      stvmp, stv_state,      danchih,    ROT0,   "Altron (Tecmo license)",       "Danchi de Hanafuda (J 990607 V1.400)", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS )
-GAME( 2000, danchiq,   stvbios, stv,      stv, stv_state,        danchiq,    ROT0,   "Altron",                       "Danchi de Quiz Okusan Yontaku Desuyo! (J 001128 V1.200)", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS )
+GAME( 2000, danchiq,   stvbios, stv,      stv, stv_state,        danchiq,    ROT0,   "Altron",                       "Danchi de Quiz: Okusan Yontaku Desuyo! (J 001128 V1.200)", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS )
 GAME( 1996, diehard,   stvbios, stv,      stv, stv_state,        diehard,    ROT0,   "Sega",                         "Die Hard Arcade (UET 960515 V1.000)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND  )
 GAME( 1996, dnmtdeka,  diehard, stv,      stv, stv_state,        dnmtdeka,   ROT0,   "Sega",                         "Dynamite Deka (J 960515 V1.000)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND  )
 GAME( 1995, ejihon,    stvbios, stv,      stv, stv_state,        stv,        ROT0,   "Sega",                         "Ejihon Tantei Jimusyo (J 950613 V1.000)", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS )
@@ -3503,7 +3505,6 @@ This is the known list of undumped ST-V games:
     Name Club (other versions)
     Print Club 2 (other versions)
     Youen Denshi Mahjong Yuugi Gal Jan
-    Danchi de Quiz: Okusan 4taku Desu yo!
     NBA Action (?)
     Quiz Omaeni Pipon Cho! (?)
 Others may exist as well...
diff --git a/src/mame/drivers/superwng.cpp b/src/mame/drivers/superwng.cpp
index 5445aab..b0df938 100644
--- a/src/mame/drivers/superwng.cpp
+++ b/src/mame/drivers/superwng.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /****************************************************************************************
 
diff --git a/src/mame/drivers/swtpc09.cpp b/src/mame/drivers/swtpc09.cpp
index 9fa2ead..96420c5 100644
--- a/src/mame/drivers/swtpc09.cpp
+++ b/src/mame/drivers/swtpc09.cpp
@@ -107,8 +107,7 @@ static MACHINE_CONFIG_START( swtpc09, swtpc09_state )
 	MCFG_RS232_RXD_HANDLER(DEVWRITELINE("acia", acia6850_device, write_rxd))
 	MCFG_RS232_CTS_HANDLER(DEVWRITELINE("acia", acia6850_device, write_cts))
 
-	MCFG_DEVICE_ADD("ptm", PTM6840, 0)
-	MCFG_PTM6840_INTERNAL_CLOCK(2000000)
+	MCFG_DEVICE_ADD("ptm", PTM6840, 2000000)
 	MCFG_PTM6840_EXTERNAL_CLOCKS(50, 0, 50)
 	MCFG_PTM6840_OUT0_CB(WRITELINE(swtpc09_state, ptm_o1_callback))
 	MCFG_PTM6840_OUT2_CB(WRITELINE(swtpc09_state, ptm_o3_callback))
@@ -148,8 +147,7 @@ static MACHINE_CONFIG_START( swtpc09i, swtpc09_state )
 	MCFG_RS232_RXD_HANDLER(DEVWRITELINE("acia", acia6850_device, write_rxd))
 	MCFG_RS232_CTS_HANDLER(DEVWRITELINE("acia", acia6850_device, write_cts))
 
-	MCFG_DEVICE_ADD("ptm", PTM6840, 0)
-	MCFG_PTM6840_INTERNAL_CLOCK(2000000)
+	MCFG_DEVICE_ADD("ptm", PTM6840, 2000000)
 	MCFG_PTM6840_EXTERNAL_CLOCKS(50, 0, 50)
 	MCFG_PTM6840_OUT0_CB(WRITELINE(swtpc09_state, ptm_o1_callback))
 	MCFG_PTM6840_OUT2_CB(WRITELINE(swtpc09_state, ptm_o3_callback))
@@ -197,8 +195,7 @@ static MACHINE_CONFIG_START( swtpc09d3, swtpc09_state )
 	MCFG_RS232_RXD_HANDLER(DEVWRITELINE("acia", acia6850_device, write_rxd))
 	MCFG_RS232_CTS_HANDLER(DEVWRITELINE("acia", acia6850_device, write_cts))
 
-	MCFG_DEVICE_ADD("ptm", PTM6840, 0)
-	MCFG_PTM6840_INTERNAL_CLOCK(2000000)
+	MCFG_DEVICE_ADD("ptm", PTM6840, 2000000)
 	MCFG_PTM6840_EXTERNAL_CLOCKS(50, 0, 50)
 	MCFG_PTM6840_OUT0_CB(WRITELINE(swtpc09_state, ptm_o1_callback))
 	MCFG_PTM6840_OUT2_CB(WRITELINE(swtpc09_state, ptm_o3_callback))
diff --git a/src/mame/drivers/system1.cpp b/src/mame/drivers/system1.cpp
index 18724cf..2322dd3 100644
--- a/src/mame/drivers/system1.cpp
+++ b/src/mame/drivers/system1.cpp
@@ -2805,6 +2805,28 @@ ROM_START( flicky )
 	ROM_LOAD( "pr-5317.76",     0x0000, 0x0100, CRC(648350b8) SHA1(c7986aa9127ef5b50b845434cb4e81dff9861cd2) )
 ROM_END
 
+// PCB label: 834-5411-11 FLICKY
+ROM_START( flickya )
+	ROM_REGION( 0x10000, "maincpu", 0 )
+	ROM_LOAD( "epr5978a.116",   0x0000, 0x4000, CRC(296f1492) SHA1(52e2c63ce376ab8124b2c68bdfa432b6621cfa78) ) /* encrypted */
+	ROM_LOAD( "epr5979a.109",   0x4000, 0x4000, CRC(64b03ef9) SHA1(7519aa7f036bce6d52a5d4be2418139559f9a8a5) ) /* encrypted */
+
+	ROM_REGION( 0x10000, "soundcpu", 0 )
+	ROM_LOAD( "epr-5869.120",   0x0000, 0x2000, CRC(6d220d4e) SHA1(fe02a7a94a1ad046fc775a7f67f460c8d0f6dca6) )
+
+	ROM_REGION( 0xc000, "tiles", 0 )
+	ROM_LOAD( "epr-6001.62",    0x0000, 0x4000, CRC(f1a75200) SHA1(47e57b5dbd687d0fa91de91f35f199e88d5a5d99) )
+	ROM_LOAD( "epr-6000.64",    0x4000, 0x4000, CRC(299aefb7) SHA1(d0301f0bf706807891845f090e4e1f1c38dbbd54) )
+	ROM_LOAD( "epr-5999.66",    0x8000, 0x4000, CRC(1ca53157) SHA1(46b4b9dac3f0506edc3957cee768e41c4754b0f4) )
+
+	ROM_REGION( 0x8000, "sprites", 0 )
+	ROM_LOAD( "epr-5855.117",   0x0000, 0x4000, CRC(b5f894a1) SHA1(2c72dc16739dad155fcd572e1add067a7647f5bd) )
+	ROM_LOAD( "epr-5856.110",   0x4000, 0x4000, CRC(266af78f) SHA1(dcbfce550d10a1f2b3ce3e7e081fc008cb575708) )
+
+	ROM_REGION( 0x0100, "proms", 0 )
+	ROM_LOAD( "pr-5317.76",     0x0000, 0x0100, CRC(648350b8) SHA1(c7986aa9127ef5b50b845434cb4e81dff9861cd2) )
+ROM_END
+
 ROM_START( flickys2 )
 	ROM_REGION( 0x10000, "maincpu", 0 )
 	ROM_LOAD( "epr-6621.bin",   0x0000, 0x4000, CRC(b21ff546) SHA1(e1d5438eaf0efeaeb4687dcfc12bf325e804182f) )
@@ -5359,8 +5381,8 @@ GAME( 1983, regulusu,   regulus,  sys1ppi,           regulus,   system1_state, b
 GAME( 1984, mrviking,   0,        sys1ppisx_315_5041,mrviking,  system1_state, bank00,       ROT270, "Sega", "Mister Viking (315-5041)", MACHINE_SUPPORTS_SAVE )
 GAME( 1984, mrvikingj,  mrviking, sys1ppisx_315_5041,mrvikingj, system1_state, bank00,       ROT270, "Sega", "Mister Viking (315-5041, Japan)", MACHINE_SUPPORTS_SAVE )
 GAME( 1984, swat,       0,        sys1ppix_315_5048, swat,      system1_state, bank00,       ROT270, "Coreland / Sega", "SWAT (315-5048)", MACHINE_SUPPORTS_SAVE )
-GAME( 1984, flickyo,    flicky,   sys1ppix_315_5051, flicky,    system1_state, bank00,       ROT0,   "Sega", "Flicky (64k Version, System 1, 315-5051, set 1)", MACHINE_SUPPORTS_SAVE )
-GAME( 1984, flickys1,   flicky,   sys1ppix_315_5051, flickys1,  system1_state, bank00,       ROT0,   "Sega", "Flicky (64k Version, System 1, 315-5051, set 2)", MACHINE_SUPPORTS_SAVE )
+GAME( 1984, flickyo,    flicky,   sys1ppix_315_5051, flicky,    system1_state, bank00,       ROT0,   "Sega", "Flicky (64k Version, 315-5051, set 1)", MACHINE_SUPPORTS_SAVE )
+GAME( 1984, flickys1,   flicky,   sys1ppix_315_5051, flickys1,  system1_state, bank00,       ROT0,   "Sega", "Flicky (64k Version, 315-5051, set 2)", MACHINE_SUPPORTS_SAVE )
 GAME( 1984, wmatch,     0,        sys1ppisx_315_5064,wmatch,    system1_state, bank00,       ROT270, "Sega", "Water Match (315-5064)", MACHINE_SUPPORTS_SAVE )
 GAME( 1984, bullfgt,    0,        sys1ppix_315_5065, bullfgt,   system1_state, bank00,       ROT0,   "Coreland / Sega", "Bullfight (315-5065)", MACHINE_SUPPORTS_SAVE )
 GAME( 1985, nprinces,   seganinj, sys1ppix_315_5051, seganinj,  system1_state, bank00,       ROT0,   "bootleg?", "Ninja Princess (315-5051, 64k Ver. bootleg?)", MACHINE_SUPPORTS_SAVE )
@@ -5372,8 +5394,9 @@ GAME( 1986, nob,        0,        nobm,              nob,       system1_state, n
 GAME( 1986, nobb,       nob,      nob,               nob,       system1_state, nobb,         ROT270, "bootleg (Game Electronics)", "Noboranka (Japan, bootleg)", MACHINE_SUPPORTS_SAVE )
 
 /* PIO-based System 1 */
-GAME( 1984, flicky,     0,        sys1piox_315_5051, flicky,    system1_state, bank00,        ROT0,   "Sega", "Flicky (128k Version, System 2, 315-5051)", MACHINE_SUPPORTS_SAVE )
-GAME( 1984, flickys2,   flicky,   sys1pio,           flickys2,  system1_state, bank00,        ROT0,   "Sega", "Flicky (128k Version, System 2, not encrypted)", MACHINE_SUPPORTS_SAVE )
+GAME( 1984, flicky,     0,        sys1piox_315_5051, flicky,    system1_state, bank00,        ROT0,   "Sega", "Flicky (128k Version, 315-5051)", MACHINE_SUPPORTS_SAVE )
+GAME( 1984, flickya,    flicky,   sys1piox_315_5051, flicky,    system1_state, bank00,        ROT0,   "Sega", "Flicky (128k Version, 315-5051, larger roms)", MACHINE_SUPPORTS_SAVE )
+GAME( 1984, flickys2,   flicky,   sys1pio,           flickys2,  system1_state, bank00,        ROT0,   "Sega", "Flicky (128k Version, not encrypted)", MACHINE_SUPPORTS_SAVE )
 GAME( 1984, thetogyu,   bullfgt,  sys1piox_315_5065, bullfgt,   system1_state, bank00,        ROT0,   "Coreland / Sega", "The Togyu (315-5065, Japan)", MACHINE_SUPPORTS_SAVE )
 GAME( 1984, spatter,    0,        sys1piosx_315_spat,spatter,   system1_state, bank00,        ROT0,   "Sega", "Spatter (315-xxxx)", MACHINE_SUPPORTS_SAVE )
 GAME( 1984, spattera,   spatter,  sys1piosx_315_5099,spatter,   system1_state, bank00,        ROT0,   "Sega", "Spatter (315-5099)", MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/drivers/system16.cpp b/src/mame/drivers/system16.cpp
index fb4bb0c..0f7bc02 100644
--- a/src/mame/drivers/system16.cpp
+++ b/src/mame/drivers/system16.cpp
@@ -122,6 +122,18 @@ WRITE16_MEMBER(segas1x_bootleg_state::sound_command_irq_w)
 	}
 }
 
+READ8_MEMBER(segas1x_bootleg_state::sound_command_irq_r)
+{
+	m_soundcpu->set_input_line(0, CLEAR_LINE);
+	return m_soundlatch->read(space, 0, 0xff);
+}
+
+WRITE8_MEMBER(segas1x_bootleg_state::soundbank_msm_w)
+{
+	m_soundbank->set_entry((data & 7) ^ 6); // probably wrong
+	m_msm->reset_w(BIT(data, 3));
+}
+
 
 static ADDRESS_MAP_START( shinobib_map, AS_PROGRAM, 16, segas1x_bootleg_state )
 	AM_RANGE(0x000000, 0x03ffff) AM_ROM
@@ -424,19 +436,24 @@ ADDRESS_MAP_END
 
 static ADDRESS_MAP_START(shinobi_datsu_sound_map, AS_PROGRAM, 8, segas1x_bootleg_state )
 	AM_RANGE(0x0000, 0x7fff) AM_ROM
-
+	AM_RANGE(0x8000, 0xbfff) AM_ROMBANK("soundbank")
 	AM_RANGE(0xe000, 0xe001) AM_DEVREADWRITE("ym1", ym2203_device, read, write)
 	AM_RANGE(0xe400, 0xe401) AM_DEVREADWRITE("ym2", ym2203_device, read, write)
-	AM_RANGE(0xe800, 0xe800) AM_DEVREAD("soundlatch", generic_latch_8_device, read)
-
+	AM_RANGE(0xe800, 0xe800) AM_READ(sound_command_irq_r)
+	AM_RANGE(0xec00, 0xec00) AM_DEVWRITE("adpcm_select", ls157_device, ba_w)
+	AM_RANGE(0xf000, 0xf000) AM_WRITE(soundbank_msm_w)
 	AM_RANGE(0xf800, 0xffff) AM_RAM
 ADDRESS_MAP_END
 
-static ADDRESS_MAP_START( shinobi_datsu_sound_io, AS_IO, 8, segas1x_bootleg_state )
-	ADDRESS_MAP_GLOBAL_MASK(0xff)
-ADDRESS_MAP_END
-
+WRITE_LINE_MEMBER(segas1x_bootleg_state::datsu_msm5205_callback)
+{
+	if (!state)
+		return;
 
+	m_sample_select = !m_sample_select;
+	m_adpcm_select->select_w(m_sample_select);
+	m_soundcpu->set_input_line(INPUT_LINE_NMI, m_sample_select);
+}
 
 /*******************************************************************************/
 
@@ -817,7 +834,7 @@ static ADDRESS_MAP_START( goldnaxeb2_map, AS_PROGRAM, 16, segas1x_bootleg_state
 	AM_RANGE(0xc44060, 0xc44067) AM_WRITE(goldnaxeb2_fgpage_w) AM_SHARE("gab2_fgpage")
 	AM_RANGE(0xc46000, 0xc46001) AM_WRITENOP
 	AM_RANGE(0xc43034, 0xc43035) AM_WRITENOP
-	AM_RANGE(0xfe0006, 0xfe0007) AM_WRITENOP
+	AM_RANGE(0xfe0006, 0xfe0007) AM_WRITE(sound_command_irq_w)
 	AM_RANGE(0xffc000, 0xffffff) AM_RAM // work ram
 ADDRESS_MAP_END
 
@@ -2062,18 +2079,15 @@ static MACHINE_CONFIG_FRAGMENT( datsu_ym2151_msm5205 )
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.80)
 MACHINE_CONFIG_END
 
-static MACHINE_CONFIG_FRAGMENT( datsu_2x_ym2203 )
+static MACHINE_CONFIG_FRAGMENT( datsu_2x_ym2203_msm5205 )
 	MCFG_CPU_ADD("soundcpu", Z80, 4000000)
-	MCFG_CPU_PERIODIC_INT_DRIVER(segas1x_bootleg_state, nmi_line_pulse,  3000) // or from the YM2203?
 	MCFG_CPU_PROGRAM_MAP(shinobi_datsu_sound_map)
-	MCFG_CPU_IO_MAP(shinobi_datsu_sound_io)
 
 	/* sound hardware */
 	MCFG_SPEAKER_STANDARD_MONO("mono")
 
 	// 2x YM2203C, one at U57, one at U56
 	MCFG_SOUND_ADD("ym1", YM2203, 4000000)
-//  MCFG_YM2203_IRQ_HANDLER(WRITELINE(segas1x_bootleg_state, datsu_irq_handler))
 	MCFG_SOUND_ROUTE(0, "mono", 0.50)
 	MCFG_SOUND_ROUTE(1, "mono", 0.50)
 	MCFG_SOUND_ROUTE(2, "mono", 0.50)
@@ -2081,10 +2095,17 @@ static MACHINE_CONFIG_FRAGMENT( datsu_2x_ym2203 )
 
 	MCFG_SOUND_ADD("ym2", YM2203, 4000000)
 	MCFG_SOUND_ROUTE(0, "mono", 0.50)
-//  MCFG_YM2203_IRQ_HANDLER(WRITELINE(segas1x_bootleg_state, datsu_irq_handler))
 	MCFG_SOUND_ROUTE(1, "mono", 0.50)
 	MCFG_SOUND_ROUTE(2, "mono", 0.50)
 	MCFG_SOUND_ROUTE(3, "mono", 0.80)
+
+	MCFG_DEVICE_ADD("adpcm_select", LS157, 0)
+	MCFG_74157_OUT_CB(DEVWRITE8("5205", msm5205_device, data_w))
+
+	MCFG_SOUND_ADD("5205", MSM5205, 384000)
+	MCFG_MSM5205_VCLK_CB(WRITELINE(segas1x_bootleg_state, datsu_msm5205_callback))
+	MCFG_MSM5205_PRESCALER_SELECTOR(MSM5205_S48_4B)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.80)
 MACHINE_CONFIG_END
 
 /*************************************
@@ -2130,7 +2151,7 @@ static MACHINE_CONFIG_DERIVED( shinobi_datsu, system16_base )
 	MCFG_SCREEN_MODIFY("screen")
 	MCFG_SCREEN_UPDATE_DRIVER(segas1x_bootleg_state, screen_update_s16a_bootleg)
 
-	MCFG_FRAGMENT_ADD(datsu_2x_ym2203)
+	MCFG_FRAGMENT_ADD(datsu_2x_ym2203_msm5205)
 MACHINE_CONFIG_END
 
 
@@ -2167,7 +2188,9 @@ static MACHINE_CONFIG_DERIVED( passsht4b, system16_base )
 	MCFG_SCREEN_MODIFY("screen")
 	MCFG_SCREEN_UPDATE_DRIVER(segas1x_bootleg_state, screen_update_s16a_bootleg_passht4b)
 
-	MCFG_FRAGMENT_ADD(datsu_2x_ym2203)
+	MCFG_FRAGMENT_ADD(datsu_2x_ym2203_msm5205)
+	MCFG_DEVICE_MODIFY("5205")
+	MCFG_MSM5205_PRESCALER_SELECTOR(MSM5205_S96_4B)
 MACHINE_CONFIG_END
 
 static MACHINE_CONFIG_DERIVED( wb3bb, system16_base )
@@ -2231,7 +2254,7 @@ static MACHINE_CONFIG_DERIVED( goldnaxeb2, goldnaxeb_base )
 	MCFG_CPU_PROGRAM_MAP(goldnaxeb2_map)
 	MCFG_DEVICE_REMOVE_ADDRESS_MAP(AS_DECRYPTED_OPCODES)
 
-	MCFG_FRAGMENT_ADD(datsu_ym2151_msm5205)
+	MCFG_FRAGMENT_ADD(datsu_2x_ym2203_msm5205)
 MACHINE_CONFIG_END
 
 
@@ -2314,7 +2337,9 @@ static MACHINE_CONFIG_DERIVED( altbeastbl, system16_base )
 	MCFG_BOOTLEG_SYS16B_SPRITES_ADD("sprites")
 	MCFG_BOOTLEG_SYS16B_SPRITES_XORIGIN(189-112)
 
-	MCFG_FRAGMENT_ADD(datsu_2x_ym2203)
+	MCFG_FRAGMENT_ADD(datsu_2x_ym2203_msm5205)
+	MCFG_DEVICE_MODIFY("5205")
+	MCFG_MSM5205_PRESCALER_SELECTOR(MSM5205_S96_4B)
 MACHINE_CONFIG_END
 
 static MACHINE_CONFIG_DERIVED( beautyb, system16_base )
@@ -2512,8 +2537,9 @@ ROM_START( shinobld )
 	ROM_LOAD16_BYTE( "7.bin", 0x60001, 0x10000, CRC(41f41063) SHA1(5cc461e9738dddf9eea06831fce3702d94674163) )
 	ROM_LOAD16_BYTE( "1.bin", 0x60000, 0x10000, CRC(b6e1fd72) SHA1(eb86e4bf880bd1a1d9bcab3f2f2e917bcaa06172) )
 
-	ROM_REGION( 0x10000, "soundcpu", 0 ) /* sound CPU + data */
+	ROM_REGION( 0x20000, "soundcpu", 0 ) /* sound CPU + data */
 	ROM_LOAD( "16.bin", 0x0000, 0x10000, CRC(52c8364e) SHA1(01d30b82f92498d155d2e31d43d58dff0285cce3) )
+	ROM_RELOAD( 0x10000, 0x10000 )
 ROM_END
 
 ROM_START( shinoblda )
@@ -2538,8 +2564,9 @@ ROM_START( shinoblda )
 	ROM_LOAD16_BYTE( "7.bin", 0x60001, 0x10000, CRC(41f41063) SHA1(5cc461e9738dddf9eea06831fce3702d94674163) )
 	ROM_LOAD16_BYTE( "1.bin", 0x60000, 0x10000, CRC(b6e1fd72) SHA1(eb86e4bf880bd1a1d9bcab3f2f2e917bcaa06172) )
 
-	ROM_REGION( 0x10000, "soundcpu", 0 ) /* sound CPU + data */
+	ROM_REGION( 0x20000, "soundcpu", 0 ) /* sound CPU + data */
 	ROM_LOAD( "16.bin", 0x0000, 0x10000, CRC(52c8364e) SHA1(01d30b82f92498d155d2e31d43d58dff0285cce3) )
+	ROM_RELOAD( 0x10000, 0x10000 )
 ROM_END
 
 /* Passing Shot Bootleg is a decrypted version of Passing Shot Japanese (passshtj). It has been heavily modified */
@@ -3582,6 +3609,11 @@ DRIVER_INIT_MEMBER(segas1x_bootleg_state,common)
 
 	m_beautyb_unkx = 0;
 
+	if (m_soundbank.found())
+	{
+		m_soundbank->configure_entries(0, 8, memregion("soundcpu")->base(), 0x4000);
+		m_soundbank->set_entry(0);
+	}
 }
 
 /* Sys16A */
@@ -3857,7 +3889,7 @@ GAME( 1988, wb3bble,     wb3,       wb3bb,       wb3b, segas1x_bootleg_state,
 GAME( 1989, bayrouteb1,  bayroute,  bayrouteb1,  bayroute, segas1x_bootleg_state,  bayrouteb1, ROT0,   "bootleg (Datsu)", "Bay Route (encrypted, protected bootleg)", MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING ) // broken sprites (due to missing/wrong irq code?)
 GAME( 1989, bayrouteb2,  bayroute,  bayrouteb2,  bayroute, segas1x_bootleg_state,  bayrouteb2, ROT0,   "bootleg (Datsu)", "Bay Route (Datsu bootleg)", MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING )
 GAME( 1989, goldnaxeb1,  goldnaxe,  goldnaxeb1,  goldnaxe, segas1x_bootleg_state,  goldnaxeb1, ROT0,   "bootleg", "Golden Axe (encrypted bootleg)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND )
-GAME( 1989, goldnaxeb2,  goldnaxe,  goldnaxeb2,  goldnaxe, segas1x_bootleg_state,  goldnaxeb2, ROT0,   "bootleg", "Golden Axe (bootleg)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
+GAME( 1989, goldnaxeb2,  goldnaxe,  goldnaxeb2,  goldnaxe, segas1x_bootleg_state,  goldnaxeb2, ROT0,   "bootleg", "Golden Axe (bootleg)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND )
 GAME( 1989, tturfbl,     tturf,     tturfbl,     tturf, segas1x_bootleg_state,     tturfbl,    ROT0,   "bootleg (Datsu)", "Tough Turf (Datsu bootleg)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND )
 GAME( 1989, dduxbl,      ddux,      dduxbl,      ddux, segas1x_bootleg_state,      dduxbl,     ROT0,   "bootleg (Datsu)", "Dynamite Dux (Datsu bootleg)", MACHINE_NOT_WORKING )
 GAME( 1988, altbeastbl,  altbeast,  altbeastbl,  tetris, segas1x_bootleg_state,    altbeastbl, ROT0,   "bootleg (Datsu)", "Altered Beast (Datsu bootleg)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND )
diff --git a/src/mame/drivers/tail2nos.cpp b/src/mame/drivers/tail2nos.cpp
index b86fac0..ffee901 100644
--- a/src/mame/drivers/tail2nos.cpp
+++ b/src/mame/drivers/tail2nos.cpp
@@ -6,8 +6,7 @@
 
     Driver by Nicola Salmoria
 
-
-    press F1+F3 to see ROM/RAM tests and the final animation
+    keep pressed F1 during POST to see ROM/RAM/GFX tests.
 
 ***************************************************************************/
 
@@ -18,13 +17,21 @@
 #include "includes/tail2nos.h"
 
 
-WRITE16_MEMBER(tail2nos_state::sound_command_w)
+WRITE8_MEMBER(tail2nos_state::sound_command_w)
+{
+	m_pending_command = 1;
+	m_soundlatch->write(space, offset, data & 0xff);
+	m_audiocpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE);
+}
+
+WRITE8_MEMBER(tail2nos_state::sound_semaphore_w)
+{
+	m_pending_command = 0;
+}
+
+READ8_MEMBER(tail2nos_state::sound_semaphore_r)
 {
-	if (ACCESSING_BITS_0_7)
-	{
-		m_soundlatch->write(space, offset, data & 0xff);
-		m_audiocpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE);
-	}
+	return m_pending_command;
 }
 
 WRITE8_MEMBER(tail2nos_state::sound_bankswitch_w)
@@ -44,9 +51,12 @@ static ADDRESS_MAP_START( main_map, AS_PROGRAM, 16, tail2nos_state )
 	AM_RANGE(0xffc300, 0xffcfff) AM_RAM
 	AM_RANGE(0xffd000, 0xffdfff) AM_RAM_WRITE(tail2nos_txvideoram_w) AM_SHARE("txvideoram")
 	AM_RANGE(0xffe000, 0xffefff) AM_RAM_DEVWRITE("palette", palette_device, write) AM_SHARE("palette")
-	AM_RANGE(0xfff000, 0xfff001) AM_READ_PORT("INPUTS") AM_WRITE(tail2nos_gfxbank_w)
+	AM_RANGE(0xfff000, 0xfff001) AM_READ_PORT("IN0") AM_WRITE(tail2nos_gfxbank_w)
+	AM_RANGE(0xfff002, 0xfff003) AM_READ_PORT("IN1")
 	AM_RANGE(0xfff004, 0xfff005) AM_READ_PORT("DSW")
-	AM_RANGE(0xfff008, 0xfff009) AM_WRITE(sound_command_w)
+	AM_RANGE(0xfff008, 0xfff009) AM_READWRITE8(sound_semaphore_r,sound_command_w,0x00ff)
+//  AM_RANGE(0xfff020, 0xfff023) V-System CRTC
+//  AM_RANGE(0xfff030, 0xfff031) link comms
 ADDRESS_MAP_END
 
 static ADDRESS_MAP_START( sound_map, AS_PROGRAM, 8, tail2nos_state )
@@ -57,23 +67,31 @@ ADDRESS_MAP_END
 
 static ADDRESS_MAP_START( sound_port_map, AS_IO, 8, tail2nos_state )
 	ADDRESS_MAP_GLOBAL_MASK(0xff)
-	AM_RANGE(0x07, 0x07) AM_DEVREAD("soundlatch", generic_latch_8_device, read) AM_WRITENOP /* the write is a clear pending command */
+	AM_RANGE(0x07, 0x07) AM_DEVREAD("soundlatch", generic_latch_8_device, read) AM_WRITE(sound_semaphore_w)
 	AM_RANGE(0x08, 0x0b) AM_DEVWRITE("ymsnd", ym2608_device, write)
 #if 0
 	AM_RANGE(0x18, 0x1b) AM_DEVREAD("ymsnd", ym2608_device, read)
 #endif
 ADDRESS_MAP_END
 
+CUSTOM_INPUT_MEMBER(tail2nos_state::analog_in_r)
+{
+	int num = (uintptr_t)param;
+	int delta = ioport(num ? "AN1" : "AN0")->read();
+
+	return delta >> 5;
+}
 
 static INPUT_PORTS_START( tail2nos )
-	PORT_START("INPUTS")
+	PORT_START("IN0")
 	PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_UNKNOWN )
 	PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_UNKNOWN )
 	PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_2WAY
 	PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_2WAY
-	PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON1 )
-	PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON2 )
-	PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_UNKNOWN )
+	PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_CONDITION("DSW", 0x4000, EQUALS, 0x4000) PORT_NAME("Brake (standard BD)")
+	PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_CONDITION("DSW", 0x4000, EQUALS, 0x4000) PORT_NAME("Accelerate (standard BD)")
+	PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW", 0x4000, EQUALS, 0x4000)
+	PORT_BIT( 0x0070, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, tail2nos_state,analog_in_r, (void *)0) PORT_CONDITION("DSW", 0x4000, NOTEQUALS, 0x4000)
 	PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_UNKNOWN )
 	PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_COIN1 )
 	PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_COIN2 )
@@ -84,8 +102,21 @@ static INPUT_PORTS_START( tail2nos )
 	PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_SERVICE1 )
 	PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_UNKNOWN )
 
+	PORT_START("IN1")
+	PORT_BIT( 0x0070, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, tail2nos_state,analog_in_r, (void *)1) PORT_CONDITION("DSW", 0x4000, NOTEQUALS, 0x4000)
+	PORT_BIT( 0x0070, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("DSW", 0x4000, EQUALS, 0x4000)
+	PORT_BIT( 0xff8f, IP_ACTIVE_LOW, IPT_UNKNOWN )
+
+	PORT_START("AN0")
+	PORT_BIT( 0xff, 0, IPT_AD_STICK_Z ) PORT_SENSITIVITY(10) PORT_KEYDELTA(5) PORT_NAME("Brake (original BD)") PORT_CONDITION("DSW", 0x4000, NOTEQUALS, 0x4000)
+	PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("DSW", 0x4000, EQUALS, 0x4000)
+
+	PORT_START("AN1")
+	PORT_BIT( 0xff, 0, IPT_AD_STICK_Z ) PORT_SENSITIVITY(10) PORT_KEYDELTA(5) PORT_NAME("Accelerate (original BD)")  PORT_CONDITION("DSW", 0x4000, NOTEQUALS, 0x4000)
+	PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("DSW", 0x4000, EQUALS, 0x4000)
+
 	PORT_START("DSW")
-	PORT_DIPNAME( 0x000f, 0x0000, DEF_STR( Coin_A ) )
+	PORT_DIPNAME( 0x000f, 0x0000, DEF_STR( Coin_A ) ) PORT_DIPLOCATION("SW1:1,2,3,4")
 	PORT_DIPSETTING(      0x0009, DEF_STR( 5C_1C ) )
 	PORT_DIPSETTING(      0x0008, DEF_STR( 4C_1C ) )
 	PORT_DIPSETTING(      0x0007, DEF_STR( 3C_1C ) )
@@ -102,7 +133,7 @@ static INPUT_PORTS_START( tail2nos )
 	PORT_DIPSETTING(      0x0003, DEF_STR( 1C_4C ) )
 	PORT_DIPSETTING(      0x0004, DEF_STR( 1C_5C ) )
 	PORT_DIPSETTING(      0x0005, DEF_STR( 1C_6C ) )
-	PORT_DIPNAME( 0x00f0, 0x0000, DEF_STR( Coin_B ) )
+	PORT_DIPNAME( 0x00f0, 0x0000, DEF_STR( Coin_B ) ) PORT_DIPLOCATION("SW1:5,6,7,8")
 	PORT_DIPSETTING(      0x0090, DEF_STR( 5C_1C ) )
 	PORT_DIPSETTING(      0x0080, DEF_STR( 4C_1C ) )
 	PORT_DIPSETTING(      0x0070, DEF_STR( 3C_1C ) )
@@ -119,25 +150,26 @@ static INPUT_PORTS_START( tail2nos )
 	PORT_DIPSETTING(      0x0030, DEF_STR( 1C_4C ) )
 	PORT_DIPSETTING(      0x0040, DEF_STR( 1C_5C ) )
 	PORT_DIPSETTING(      0x0050, DEF_STR( 1C_6C ) )
-	PORT_DIPNAME( 0x0300, 0x0000, DEF_STR( Difficulty ) )
+	PORT_DIPNAME( 0x0300, 0x0000, DEF_STR( Difficulty ) ) PORT_DIPLOCATION("SW2:1,2")
 	PORT_DIPSETTING(      0x0100, DEF_STR( Easy ) )
 	PORT_DIPSETTING(      0x0000, DEF_STR( Normal ) )
 	PORT_DIPSETTING(      0x0200, DEF_STR( Hard ) )
 	PORT_DIPSETTING(      0x0300, DEF_STR( Hardest ) )
-	PORT_DIPNAME( 0x0400, 0x0000, DEF_STR( Demo_Sounds ) )
+	PORT_DIPNAME( 0x0400, 0x0000, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SW2:3")
 	PORT_DIPSETTING(      0x0400, DEF_STR( Off ) )
 	PORT_DIPSETTING(      0x0000, DEF_STR( On ) )
-	PORT_SERVICE( 0x0800, IP_ACTIVE_HIGH )
-	PORT_DIPNAME( 0x1000, 0x1000, "Game Mode" )
+	PORT_SERVICE_DIPLOC( 0x0800, IP_ACTIVE_HIGH, "SW2:4" )
+	PORT_DIPNAME( 0x1000, 0x1000, "Game Mode" ) PORT_DIPLOCATION("SW2:5")
 	PORT_DIPSETTING(      0x1000, DEF_STR( Single ) )
 	PORT_DIPSETTING(      0x0000, "Multiple" )
-	PORT_DIPNAME( 0x2000, 0x0000, DEF_STR( Flip_Screen ) )
+	PORT_DIPNAME( 0x2000, 0x0000, DEF_STR( Flip_Screen ) ) PORT_DIPLOCATION("SW2:6")
 	PORT_DIPSETTING(      0x0000, DEF_STR( Off ) )
 	PORT_DIPSETTING(      0x2000, DEF_STR( On ) )
-	PORT_DIPNAME( 0x4000, 0x4000, "Control Panel" )
+	PORT_DIPNAME( 0x4000, 0x4000, "Control Panel" ) PORT_DIPLOCATION("SW2:7")
 	PORT_DIPSETTING(      0x4000, DEF_STR( Standard ) )
 	PORT_DIPSETTING(      0x0000, "Original" )
-	PORT_DIPNAME( 0x8000, 0x0000, "Country" )
+	// TODO: what's this for?
+	PORT_DIPNAME( 0x8000, 0x0000, "Country" ) PORT_DIPLOCATION("SW2:8")
 	PORT_DIPSETTING(      0x0000, "Domestic" )
 	PORT_DIPSETTING(      0x8000, "Overseas" )
 INPUT_PORTS_END
@@ -186,6 +218,7 @@ void tail2nos_state::machine_start()
 	save_item(NAME(m_txbank));
 	save_item(NAME(m_txpalette));
 	save_item(NAME(m_video_enable));
+	save_item(NAME(m_pending_command));
 }
 
 void tail2nos_state::machine_reset()
diff --git a/src/mame/drivers/taito_o.cpp b/src/mame/drivers/taito_o.cpp
index 642a677..224d5f3 100644
--- a/src/mame/drivers/taito_o.cpp
+++ b/src/mame/drivers/taito_o.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /***************************************************************
 
diff --git a/src/mame/drivers/taitojc.cpp b/src/mame/drivers/taitojc.cpp
index 8a0187f..8e85765 100644
--- a/src/mame/drivers/taitojc.cpp
+++ b/src/mame/drivers/taitojc.cpp
@@ -1452,7 +1452,73 @@ ROM_START( sidebs2u ) /* Side by Side 2 Ver 2.6 A */
 	*/
 ROM_END
 
-ROM_START( sidebs2j ) /* Side by Side 2 Evoluzione Ver 2.4 J */
+ROM_START( sidebs2j ) /* Side by Side 2 Evoluzione RR Ver 3.1 J */
+	ROM_REGION(0x200000, "maincpu", 0)      /* 68040 code */
+	ROM_LOAD32_BYTE( "e38-32.ic36", 0x000000, 0x80000, CRC(88385c6e) SHA1(935b4892a8322a73a8afdf0bd3799c4b11510ac9) )
+	ROM_LOAD32_BYTE( "e38-33.ic37", 0x000001, 0x80000, CRC(d02a9963) SHA1(74d567869b79a7e129a2e5876900e7fecb70d568) )
+	ROM_LOAD32_BYTE( "e38-34.ic38", 0x000002, 0x80000, CRC(7c4d8176) SHA1(89c5da4c60f88bca95980b1829015a6def2eabd5) )
+	ROM_LOAD32_BYTE( "e38-35.ic39", 0x000003, 0x80000, CRC(8746188d) SHA1(de7f611195cd9359328821a0c0c63ac079fad341) )
+
+	ROM_REGION( 0x180000, "taito_en:audiocpu", 0 )       /* 68000 Code */
+	ROM_LOAD16_BYTE( "e38-19.ic30", 0x100001, 0x040000, CRC(3f50cb7b) SHA1(76af65c9b74ede843a3182f79cecda8c3e3febe6) )
+	ROM_LOAD16_BYTE( "e38-20.ic31", 0x100000, 0x040000, CRC(d01340e7) SHA1(76ee48d644dc1ec415d47e0df4864c64ac928b9d) )
+
+	ROM_REGION( 0x4000, "dsp", ROMREGION_ERASE00 ) /* TMS320C51 internal rom */
+	ROM_LOAD16_WORD( "e07-11.ic29", 0x0000, 0x4000, NO_DUMP )
+
+	ROM_REGION( 0x010000, "sub", 0 )        /* MC68HC11M0 code */
+	ROM_LOAD( "e17-23.ic65",  0x000000, 0x010000, CRC(80ac1428) SHA1(5a2a1e60a11ecdb8743c20ddacfb61f9fd00f01c) )
+
+	ROM_REGION( 0x1800000, "gfx1", 0 )
+	ROM_LOAD32_WORD( "e38-05.ic9",  0x0800002, 0x200000, CRC(bda366bf) SHA1(a7558e6d5e4583a2d8e3d2bfa8cabcc459d3ee83) )
+	ROM_LOAD32_WORD( "e38-13.ic22", 0x0800000, 0x200000, CRC(1bd7582b) SHA1(35763b9489f995433f66ef72d4f6b6ac67df5480) )
+	ROM_LOAD32_WORD( "e38-06.ic10", 0x0c00002, 0x200000, CRC(308d2783) SHA1(22c309273444bc6c1df78069850958a739664998) )
+	ROM_LOAD32_WORD( "e38-14.ic23", 0x0c00000, 0x200000, CRC(f1699f27) SHA1(3c9a9cefe6f215fd9f0a9746da97147d14df1da4) )
+	ROM_LOAD32_WORD( "e38-07.ic11", 0x1000002, 0x200000, CRC(226ba93d) SHA1(98e6342d070ddd988c1e9bff21afcfb28df86844) )
+	ROM_LOAD32_WORD( "e38-15.ic24", 0x1000000, 0x200000, CRC(2853c2e3) SHA1(046dbbd4bcb3b07cddab19a284fee9fe736f8def) )
+	ROM_LOAD32_WORD( "e38-08.ic12", 0x1400002, 0x200000, CRC(9c513b32) SHA1(fe26e39d3d65073d23d525bc17771f0c244a38c2) )
+	ROM_LOAD32_WORD( "e38-16.ic25", 0x1400000, 0x200000, CRC(fceafae2) SHA1(540ecd5d1aa64c0428a08ea1e4e634e00f7e6bd6) )
+
+	ROM_REGION( 0x1000000, "gfx2", 0 )      /* only accessible to the TMS */
+	ROM_LOAD( "e38-01.ic5",  0x0000000, 0x200000, CRC(a3c2e2c7) SHA1(538208534f996782167e4cf0d157ad93ce2937bd) )
+	ROM_LOAD( "e38-02.ic6",  0x0200000, 0x200000, CRC(ecdfb75a) SHA1(85e7afa321846816fa3bd9074ad9dec95abe23fe) )
+	ROM_LOAD( "e38-03.ic7",  0x0400000, 0x200000, CRC(28e9cb59) SHA1(a2651fd81a1263573f868864ee049f8fc4177ffa) )
+	ROM_LOAD( "e38-04.ic8",  0x0600000, 0x080000, CRC(26cab05b) SHA1(d5bcf021646dade834840051e0ce083319c53985) )
+	ROM_RELOAD(              0x0680000, 0x080000 )
+	ROM_RELOAD(              0x0700000, 0x080000 )
+	ROM_RELOAD(              0x0780000, 0x080000 )
+	ROM_LOAD( "e38-09.ic18", 0x0800000, 0x200000, CRC(03c95a7f) SHA1(fc046cf5fcfcf5648f68af4bed78576f6d67b32f) )
+	ROM_LOAD( "e38-10.ic19", 0x0a00000, 0x200000, CRC(0fb06794) SHA1(2d0e3b07ded698235572fe9e907a84d5779ac2c5) )
+	ROM_LOAD( "e38-11.ic20", 0x0c00000, 0x200000, CRC(6a312351) SHA1(8037e377f8eef4cc6dd84aec9c829106f0bb130c) )
+	ROM_LOAD( "e38-12.ic21", 0x0e00000, 0x080000, CRC(193a5774) SHA1(aa017ae4fec92bb87c0eb94f59d093853ddbabc9) )
+	ROM_RELOAD(              0x0e80000, 0x080000 )
+	ROM_RELOAD(              0x0f00000, 0x080000 )
+	ROM_RELOAD(              0x0f80000, 0x080000 )
+
+	ROM_REGION16_BE( 0x1000000, "ensoniq.0", ROMREGION_ERASE00  )
+	ROM_LOAD16_BYTE( "e23-15.ic32", 0x000000, 0x200000, CRC(8955b7c7) SHA1(767626bd5cf6810b0368ee85e487c12ef7e8a23d) ) // from sidebs (redump)
+	ROM_LOAD16_BYTE( "e38-17.ic33", 0x400000, 0x200000, CRC(61e81c7f) SHA1(aa650bc139685ad456c233b79aa60005a8fd6d79) )
+	ROM_LOAD16_BYTE( "e38-18.ic34", 0x800000, 0x200000, CRC(43e2f149) SHA1(32ea9156948a886dda5bd071e9f493ddc2b06212) )
+	ROM_LOAD16_BYTE( "e38-21.ic35", 0xc00000, 0x200000, CRC(25373c5f) SHA1(ab9f917dbde7c808be2cd836ce2d3fc558e290f1) )
+
+	/* PALS
+	e23-28.ic18    NOT A ROM
+	e23-27.ic13    NOT A ROM
+	e23-26.ic4     NOT A ROM
+	e23-25-1.ic3   NOT A ROM
+	e23-30.ic40    NOT A ROM
+	e23-29.ic39    NOT A ROM
+	e23-31.ic46    NOT A ROM
+	e23-32-1.ic51  NOT A ROM
+	e23-34.ic72    NOT A ROM
+	e23-33.ic53    NOT A ROM
+	e23-35.ic110   NOT A ROM
+	e23-38.ic73    NOT A ROM
+	e23-37.ic69    NOT A ROM
+	*/
+ROM_END
+
+ROM_START( sidebs2ja ) /* Side by Side 2 Evoluzione Ver 2.4 J */
 	ROM_REGION(0x200000, "maincpu", 0)      /* 68040 code */
 	ROM_LOAD32_BYTE( "e38-23+.ic36", 0x000000, 0x80000, CRC(b3d8e2d9) SHA1(6de6a51c3d9ace532fa03517bab93101b5a3eaae) ) /* Actual label E38-23* */
 	ROM_LOAD32_BYTE( "e38-24+.ic37", 0x000001, 0x80000, CRC(2a47d80d) SHA1(41b889e4a1397c7f0d4f6ef136ed8abfd7e1ed86) ) /* Actual label E38-24* */
@@ -1993,6 +2059,7 @@ GAMEL(1996, dendego,   0,        dendego, dendego,  taitojc_state, taitojc,  ROT
 GAMEL(1996, dendegox,  dendego,  dendego, dendego,  taitojc_state, taitojc,  ROT0, "Taito", "Densha de GO! EX (Ver 2.4 J)",                         MACHINE_IMPERFECT_GRAPHICS, layout_dendego ) // DENSYA DE GO           VER 2.4 J   1997/ 4/18   13:38:34
 GAME( 1997, sidebs2,   0,        taitojc, sidebs,   taitojc_state, taitojc,  ROT0, "Taito", "Side by Side 2 (Ver 2.6 OK)",                          MACHINE_IMPERFECT_GRAPHICS )                 // SIDE BY SIDE2          VER 2.6 OK  1997/ 6/ 4   17:27:37
 GAME( 1997, sidebs2u,  sidebs2,  taitojc, sidebs,   taitojc_state, taitojc,  ROT0, "Taito", "Side by Side 2 (Ver 2.6 A)",                           MACHINE_IMPERFECT_GRAPHICS )                 // SIDE BY SIDE2          VER 2.6 A   1997/ 6/19   09:39:22
-GAME( 1997, sidebs2j,  sidebs2,  taitojc, sidebs,   taitojc_state, taitojc,  ROT0, "Taito", "Side by Side 2 Evoluzione (Ver 2.4 J)",                MACHINE_IMPERFECT_GRAPHICS )                 // SIDE BY SIDE2          VER 2.4 J   1997/ 5/26   13:06:37
+GAME( 1997, sidebs2j,  sidebs2,  taitojc, sidebs,   taitojc_state, taitojc,  ROT0, "Taito", "Side by Side 2 Evoluzione RR (Ver 3.1 J)",             MACHINE_IMPERFECT_GRAPHICS )                 // SIDE BY SIDE2          VER 3.1 J   1997/10/ 7   13:55:38
+GAME( 1997, sidebs2ja, sidebs2,  taitojc, sidebs,   taitojc_state, taitojc,  ROT0, "Taito", "Side by Side 2 Evoluzione (Ver 2.4 J)",                MACHINE_IMPERFECT_GRAPHICS )                 // SIDE BY SIDE2          VER 2.4 J   1997/ 5/26   13:06:37
 GAMEL(1998, dendego2,  0,        dendego, dendego,  taitojc_state, dendego2, ROT0, "Taito", "Densha de GO! 2 Kousoku-hen (Ver 2.5 J)",              MACHINE_IMPERFECT_GRAPHICS, layout_dendego ) // DENSYA DE GO2          VER 2.5 J   1998/ 3/ 2   15:30:55
 GAMEL(1998, dendego23k,dendego2, dendego, dendego,  taitojc_state, dendego2, ROT0, "Taito", "Densha de GO! 2 Kousoku-hen 3000-bandai (Ver 2.20 J)", MACHINE_IMPERFECT_GRAPHICS, layout_dendego ) // DENSYA DE GO! 2 3000   VER 2.20 J  1998/ 7/15   17:42:38
diff --git a/src/mame/drivers/taitosj.cpp b/src/mame/drivers/taitosj.cpp
index eeff2ff..896eabe 100644
--- a/src/mame/drivers/taitosj.cpp
+++ b/src/mame/drivers/taitosj.cpp
@@ -2523,7 +2523,7 @@ ROM_END
 
 ROM_START( elevator4 ) // later 4 board set, with rom data on 2764s, split between gfx and cpu data.
 	ROM_REGION( 0x12000, "maincpu", 0 ) // on L-shaped rom board
-	ROM_LOAD( "ba3__01.2764.ic1",  0x0000, 0x2000, CRC(da775a24) SHA1(b4341d2c87285d7a3d1773e2d94B3f621ebb4489) ) // == ea_12.2732.ic69 + ea_13.2732.ic68
+	ROM_LOAD( "ba3__01.2764.ic1",  0x0000, 0x2000, CRC(da775a24) SHA1(b4341d2c87285d7a3d1773e2d94b3f621ebb4489) ) // == ea_12.2732.ic69 + ea_13.2732.ic68
 	ROM_LOAD( "ba3__02.2764.ic2",  0x2000, 0x2000, CRC(fbfd8b3a) SHA1(9dff36dcaf43a2403b9a3497512dfec228144a7c) ) // == ea_14.2732.ic67 + ea_15.2732.ic66
 	ROM_LOAD( "ba3__03-1.2764.ic3",0x4000, 0x2000, CRC(a2e69833) SHA1(0f324c3adec27fcfebd779328db6f1da6cc8d227) ) // == ea_16.2732.ic65 + ea_17.2732.ic64
 	ROM_LOAD( "ba3__04-1.2764.ic6",0x6000, 0x2000, CRC(2b78c462) SHA1(ae41e0089c7f445fa271f6af7e141b112f0009e6) ) // == ea_18.2732.ic55 + ea_19.2732.ic54
diff --git a/src/mame/drivers/tattack.cpp b/src/mame/drivers/tattack.cpp
index 84da25e..5f3bb04 100644
--- a/src/mame/drivers/tattack.cpp
+++ b/src/mame/drivers/tattack.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /****************************************************************************
     Time Attacker
diff --git a/src/mame/drivers/tavernie.cpp b/src/mame/drivers/tavernie.cpp
index cbd201e..8949615 100644
--- a/src/mame/drivers/tavernie.cpp
+++ b/src/mame/drivers/tavernie.cpp
@@ -317,9 +317,8 @@ static MACHINE_CONFIG_START( cpu09, tavernie_state )
 	MCFG_PIA_IRQA_HANDLER(INPUTLINE("maincpu", M6809_IRQ_LINE))
 	MCFG_PIA_IRQB_HANDLER(INPUTLINE("maincpu", M6809_IRQ_LINE))
 
-	MCFG_DEVICE_ADD("ptm", PTM6840, 0)
+	MCFG_DEVICE_ADD("ptm", PTM6840, XTAL_4MHz / 4)
 	// all i/o lines connect to the 40-pin expansion connector
-	MCFG_PTM6840_INTERNAL_CLOCK(XTAL_4MHz / 4)
 	MCFG_PTM6840_EXTERNAL_CLOCKS(0, 0, 0)
 	MCFG_PTM6840_OUT1_CB(INPUTLINE("maincpu", INPUT_LINE_NMI))
 	MCFG_PTM6840_IRQ_CB(INPUTLINE("maincpu", M6809_IRQ_LINE))
diff --git a/src/mame/drivers/tcl.cpp b/src/mame/drivers/tcl.cpp
index 0cbc2e6..88e4345 100644
--- a/src/mame/drivers/tcl.cpp
+++ b/src/mame/drivers/tcl.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /*
 Taiwan Chess Legend
diff --git a/src/mame/drivers/tecmo16.cpp b/src/mame/drivers/tecmo16.cpp
index b1a33a4..6a34ed9 100644
--- a/src/mame/drivers/tecmo16.cpp
+++ b/src/mame/drivers/tecmo16.cpp
@@ -13,7 +13,7 @@ driver by Hau, Nicola Salmoria
 special thanks to Nekomata, NTD & code-name'Siberia'
 
 TODO:
-- wrong background in fstarfrc title
+- wrong background in fstarfrc title (Video ref. -> https://www.youtube.com/watch?v=EXBTNk-0ejk)
 - there could be some priorities problems in riot
   (more noticeable in level 2)
 
@@ -397,7 +397,7 @@ static MACHINE_CONFIG_START( fstarfrc, tecmo16_state )
 	MCFG_TECMO_MIXER_SHIFTS(10,9,4)
 	MCFG_TECMO_MIXER_BLENDCOLS(   0x0400 + 0x300, 0x0400 + 0x200, 0x0400 + 0x100, 0x0400 + 0x000 )
 	MCFG_TECMO_MIXER_REGULARCOLS( 0x0000 + 0x300, 0x0000 + 0x200, 0x0000 + 0x100, 0x0000 + 0x000 )
-	MCFG_TECMO_MIXER_BLENDSOUCE( 0x0800 + 0x000, 0x0800 + 0x100) // riot seems to set palettes in 0x800 + 0x200, could be more to this..
+	MCFG_TECMO_MIXER_BLENDSOURCE( 0x0800 + 0x000, 0x0800 + 0x100) // riot seems to set palettes in 0x800 + 0x200, could be more to this..
 	MCFG_TECMO_MIXER_REVSPRITETILE
 	MCFG_TECMO_MIXER_BGPEN(0x000 + 0x300)
 
diff --git a/src/mame/drivers/tmaster.cpp b/src/mame/drivers/tmaster.cpp
index 5656d23..4515012 100644
--- a/src/mame/drivers/tmaster.cpp
+++ b/src/mame/drivers/tmaster.cpp
@@ -1723,6 +1723,13 @@ PAL16V8H-15 @ U26   Red dot on it
 PAL16V8H-15 @ U27   Green dot on it
 PAL16V8H-15 @ U45   red dot on it
 
+4 known game carts where produced, these are:
+
+Star Pak 1: Unknown
+Star Pak 2: Pack-Man, Ms.Pac-Man, Pharaoh's Tomb, Solar Solitaire, Power Pairs, Seek The peeks & Have A Cow
+Star PaK 3: Centipede, Great Wall, Ker-Chunk, Diamond Derby, Word Sleuth, Pull!, Astro Blast & Sweeper
+Star Pak 4: Unknown
+
 ***************************************************************************/
 
 #define GALGAMES_BIOS_ROMS \
diff --git a/src/mame/drivers/tmnt.cpp b/src/mame/drivers/tmnt.cpp
index 3643840..0c4dfaf 100644
--- a/src/mame/drivers/tmnt.cpp
+++ b/src/mame/drivers/tmnt.cpp
@@ -1696,118 +1696,57 @@ static INPUT_PORTS_START( ssriders )
 INPUT_PORTS_END
 
 static INPUT_PORTS_START( ssridr4p )
-	PORT_START("COINS")
-	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 )
-	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 )
+		PORT_INCLUDE( ssriders )
+
+	PORT_MODIFY("COINS")
 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_COIN3 )
 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_COIN4 )
-	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_SERVICE1 )
-	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_SERVICE2 )
 	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SERVICE3 )
 	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_SERVICE4 )
 
-	PORT_START("P1")
+	PORT_MODIFY("P1")
 	KONAMI16_LSB( 1, IPT_UNKNOWN, IPT_UNKNOWN )
 
-	PORT_START("P2")
+	PORT_MODIFY("P2")
 	KONAMI16_LSB( 2, IPT_UNKNOWN, IPT_UNKNOWN )
 
-	PORT_START("P3")
+	PORT_MODIFY("P3")
 	KONAMI16_LSB( 3, IPT_UNKNOWN, IPT_UNKNOWN )
 
-	PORT_START("P4")
+	PORT_MODIFY("P4")
 	KONAMI16_LSB( 4, IPT_UNKNOWN, IPT_UNKNOWN )
 
-	PORT_START("EEPROM")
-	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_READ_LINE_DEVICE_MEMBER("eeprom", eeprom_serial_er5911_device, do_read)
-	PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_READ_LINE_DEVICE_MEMBER("eeprom", eeprom_serial_er5911_device, ready_read)
-	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN )    /* ?? TMNT2: OBJMPX */
-	PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_VBLANK("screen")  /* ?? TMNT2: NVBLK */
-	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )    /* ?? TMNT2: IPL0 */
-	PORT_BIT( 0x60, IP_ACTIVE_LOW, IPT_UNKNOWN )    /* unused? */
-	PORT_SERVICE_NO_TOGGLE( 0x80, IP_ACTIVE_LOW )
-
-	PORT_START( "EEPROMOUT" )
-	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_DEVICE_MEMBER("eeprom", eeprom_serial_er5911_device, di_write)
-	PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_DEVICE_MEMBER("eeprom", eeprom_serial_er5911_device, cs_write)
-	PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_DEVICE_MEMBER("eeprom", eeprom_serial_er5911_device, clk_write)
 INPUT_PORTS_END
 
-/* Same as 'ssridr4p', but additional Start button for each player.
+/* Same as 'ssridr4p', but additional Start button for each player.  Seemingly only needed in sets with *U* region/version codes (EG: ADD, UDA).
    COIN3, COIN4, SERVICE3 and SERVICE4 only have an effect in the "test mode". */
 static INPUT_PORTS_START( ssrid4ps )
-	PORT_START("COINS")
-	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 )
-	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 )
-	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_COIN3 )
-	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_COIN4 )
-	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_SERVICE1 )
-	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_SERVICE2 )
-	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SERVICE3 )
-	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_SERVICE4 )
 
-	PORT_START("P1")
+	PORT_INCLUDE( ssridr4p )
+
+	PORT_MODIFY("P1")
 	KONAMI16_LSB( 1, IPT_UNKNOWN, IPT_START1 )
 
-	PORT_START("P2")
+	PORT_MODIFY("P2")
 	KONAMI16_LSB( 2, IPT_UNKNOWN, IPT_START2 )
 
-	PORT_START("P3")
+	PORT_MODIFY("P3")
 	KONAMI16_LSB( 3, IPT_UNKNOWN, IPT_START3 )
 
-	PORT_START("P4")
+	PORT_MODIFY("P4")
 	KONAMI16_LSB( 4, IPT_UNKNOWN, IPT_START4 )
 
-	PORT_START("EEPROM")
-	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_READ_LINE_DEVICE_MEMBER("eeprom", eeprom_serial_er5911_device, do_read)
-	PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_READ_LINE_DEVICE_MEMBER("eeprom", eeprom_serial_er5911_device, ready_read)
-	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN )    /* ?? TMNT2: OBJMPX */
-	PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_VBLANK("screen")  /* ?? TMNT2: NVBLK */
-	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )    /* ?? TMNT2: IPL0 */
-	PORT_BIT( 0x60, IP_ACTIVE_LOW, IPT_UNKNOWN )    /* unused? */
-	PORT_SERVICE_NO_TOGGLE( 0x80, IP_ACTIVE_LOW )
-
-	PORT_START( "EEPROMOUT" )
-	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_DEVICE_MEMBER("eeprom", eeprom_serial_er5911_device, di_write)
-	PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_DEVICE_MEMBER("eeprom", eeprom_serial_er5911_device, cs_write)
-	PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_DEVICE_MEMBER("eeprom", eeprom_serial_er5911_device, clk_write)
 INPUT_PORTS_END
 
 /* Version for the bootleg, which has the service switch a little different */
 static INPUT_PORTS_START( sunsetbl )
-	PORT_START("COINS")
-	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 )
-	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 )
-	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_COIN3 )
-	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_COIN4 )
-	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_SERVICE1 )
-	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_SERVICE2 )
-	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SERVICE3 )
-	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_SERVICE4 )
 
-	PORT_START("P1")
-	KONAMI16_LSB( 1, IPT_UNKNOWN, IPT_START1 )
-
-	PORT_START("P2")
-	KONAMI16_LSB( 2, IPT_UNKNOWN, IPT_START2 )
+	PORT_INCLUDE( ssrid4ps )
 
-	PORT_START("P3")
-	KONAMI16_LSB( 3, IPT_UNKNOWN, IPT_START3 )
-
-	PORT_START("P4")
-	KONAMI16_LSB( 4, IPT_UNKNOWN, IPT_START4 )
-
-	PORT_START("EEPROM")
-	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_READ_LINE_DEVICE_MEMBER("eeprom", eeprom_serial_er5911_device, do_read)
-	PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_READ_LINE_DEVICE_MEMBER("eeprom", eeprom_serial_er5911_device, ready_read)
-	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN )
+	PORT_MODIFY("EEPROM")
 	PORT_SERVICE_NO_TOGGLE( 0x08, IP_ACTIVE_LOW )
 	PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_UNKNOWN )    /* unused? */
 
-	PORT_START( "EEPROMOUT" )
-	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_DEVICE_MEMBER("eeprom", eeprom_serial_er5911_device, di_write)
-	PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_DEVICE_MEMBER("eeprom", eeprom_serial_er5911_device, cs_write)
-	PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_DEVICE_MEMBER("eeprom", eeprom_serial_er5911_device, clk_write)
 INPUT_PORTS_END
 
 static INPUT_PORTS_START( qgakumon )
@@ -4303,7 +4242,7 @@ GAME( 1991, tmnt22pu,    tmnt2,    tmnt2,    ssriders,  driver_device, 0,
 GAME( 1993, qgakumon,    0,        tmnt2,    qgakumon,  driver_device, 0,        ROT0,   "Konami", "Quiz Gakumon no Susume (Japan ver. JA2 Type L)", MACHINE_SUPPORTS_SAVE )
 
 GAME( 1991, ssriders,    0,        ssriders, ssridr4p,  driver_device, 0,        ROT0,   "Konami", "Sunset Riders (4 Players ver EAC)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
-GAME( 1991, ssriderseaa, ssriders, ssriders, ssrid4ps,  driver_device, 0,        ROT0,   "Konami", "Sunset Riders (4 Players ver EAA)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
+GAME( 1991, ssriderseaa, ssriders, ssriders, ssridr4p,  driver_device, 0,        ROT0,   "Konami", "Sunset Riders (4 Players ver EAA)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
 GAME( 1991, ssridersebd, ssriders, ssriders, ssriders,  driver_device, 0,        ROT0,   "Konami", "Sunset Riders (2 Players ver EBD)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
 GAME( 1991, ssridersebc, ssriders, ssriders, ssriders,  driver_device, 0,        ROT0,   "Konami", "Sunset Riders (2 Players ver EBC)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
 GAME( 1991, ssridersuda, ssriders, ssriders, ssrid4ps,  driver_device, 0,        ROT0,   "Konami", "Sunset Riders (4 Players ver UDA)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
@@ -4312,8 +4251,8 @@ GAME( 1991, ssridersuab, ssriders, ssriders, ssridr4p,  driver_device, 0,
 GAME( 1991, ssridersubc, ssriders, ssriders, ssriders,  driver_device, 0,        ROT0,   "Konami", "Sunset Riders (2 Players ver UBC)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
 GAME( 1991, ssridersadd, ssriders, ssriders, ssrid4ps,  driver_device, 0,        ROT0,   "Konami", "Sunset Riders (4 Players ver ADD)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
 GAME( 1991, ssridersabd, ssriders, ssriders, ssriders,  driver_device, 0,        ROT0,   "Konami", "Sunset Riders (2 Players ver ABD)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
-GAME( 1991, ssridersjad, ssriders, ssriders, ssrid4ps,  driver_device, 0,        ROT0,   "Konami", "Sunset Riders (4 Players ver JAD)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
-GAME( 1991, ssridersjac, ssriders, ssriders, ssrid4ps,  driver_device, 0,        ROT0,   "Konami", "Sunset Riders (4 Players ver JAC)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
+GAME( 1991, ssridersjad, ssriders, ssriders, ssridr4p,  driver_device, 0,        ROT0,   "Konami", "Sunset Riders (4 Players ver JAD)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
+GAME( 1991, ssridersjac, ssriders, ssriders, ssridr4p,  driver_device, 0,        ROT0,   "Konami", "Sunset Riders (4 Players ver JAC)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
 GAME( 1991, ssridersjbd, ssriders, ssriders, ssriders,  driver_device, 0,        ROT0,   "Konami", "Sunset Riders (2 Players ver JBD)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
 GAME( 1991, ssridersb,   ssriders, sunsetbl, sunsetbl,  driver_device, 0,        ROT0,   "bootleg","Sunset Riders (bootleg 4 Players ver ADD)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
 GAME( 1991, ssriders2,   ssriders, sunsetbl, sunsetbl,  driver_device, 0,        ROT0,   "bootleg","Sunset Riders 2 (bootleg 4 Players ver ADD)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/drivers/tnzs.cpp b/src/mame/drivers/tnzs.cpp
index c24812c..ce778c8 100644
--- a/src/mame/drivers/tnzs.cpp
+++ b/src/mame/drivers/tnzs.cpp
@@ -413,7 +413,7 @@ TODO:
 - Find out how the hardware credit-counter works (MPU)
 - Fix MCU simulation errors :
     * avoid credits to be increased when in "test mode" to avoid coin lockout
-      (needed to complete special test mode in 'extermatn' and 'arknoid2')
+      (needed to complete special test mode in 'extrmatn' and 'arknoid2')
     * why are credits limited to 9 in some games ?
       pressing SERVICE1 allows to go up to 100 and cause this :
         . 'plumppop' : freeze
@@ -628,41 +628,30 @@ Driver by Takahiro Nogi (nogi at kt.rim.or.jp) 1999/11/06
 #include "sound/volt_reg.h"
 #include "sound/ym2151.h"
 
-SAMPLES_START_CB_MEMBER(tnzs_state::kageki_init_samples)
+SAMPLES_START_CB_MEMBER(kageki_state::init_samples)
 {
-	uint8_t *scan, *src;
-	int16_t *dest;
-	int start, size;
-	int i, n;
-
-	src = memregion("samples")->base() + 0x0090;
-	for (i = 0; i < MAX_SAMPLES; i++)
+	uint8_t *src = memregion("samples")->base() + 0x0090;
+	for (int i = 0; i < MAX_SAMPLES; i++)
 	{
-		start = (src[(i * 2) + 1] * 256) + src[(i * 2)];
-		scan = &src[start];
-		size = 0;
+		int start = (src[(i * 2) + 1] * 256) + src[(i * 2)];
+		uint8_t *scan = &src[start];
+		int size = 0;
 
 		// check sample length
-		while (1)
-		{
-			if (*scan++ == 0x00)
-				break;
-			else
-				size++;
-		}
+		while (*scan++ != 0x00)
+			size++;
 
 		/* 2009-11 FP: should these be saved? */
 		m_sampledata[i] = std::make_unique<int16_t[]>(size);
 		m_samplesize[i] = size;
 
-
 		if (start < 0x100)
 			start = size = 0;
 
 		// signed 8-bit sample to unsigned 8-bit sample convert
-		dest = m_sampledata[i].get();
+		int16_t *dest = m_sampledata[i].get();
 		scan = &src[start];
-		for (n = 0; n < size; n++)
+		for (int n = 0; n < size; n++)
 		{
 			*dest++ = (int8_t)((*scan++) ^ 0x80) * 256;
 		}
@@ -671,14 +660,14 @@ SAMPLES_START_CB_MEMBER(tnzs_state::kageki_init_samples)
 }
 
 
-READ8_MEMBER(tnzs_state::kageki_csport_r)
+READ8_MEMBER(kageki_state::csport_r)
 {
 	int dsw, dsw1, dsw2;
 
 	dsw1 = m_dswa->read();
 	dsw2 = m_dswb->read();
 
-	switch (m_kageki_csport_sel)
+	switch (m_csport_sel)
 	{
 		case    0x00:           // DSW2 5,1 / DSW1 5,1
 			dsw = (((dsw2 & 0x10) >> 1) | ((dsw2 & 0x01) << 2) | ((dsw1 & 0x10) >> 3) | ((dsw1 & 0x01) >> 0));
@@ -694,20 +683,20 @@ READ8_MEMBER(tnzs_state::kageki_csport_r)
 			break;
 		default:
 			dsw = 0x00;
-		//  logerror("kageki_csport_sel error !! (0x%08X)\n", m_kageki_csport_sel);
+		//  logerror("csport_sel error !! (0x%08X)\n", m_csport_sel);
 	}
 
 	return (dsw & 0xff);
 }
 
-WRITE8_MEMBER(tnzs_state::kageki_csport_w)
+WRITE8_MEMBER(kageki_state::csport_w)
 {
 	char mess[80];
 
 	if (data > 0x3f)
 	{
 		// read dipsw port
-		m_kageki_csport_sel = (data & 0x03);
+		m_csport_sel = (data & 0x03);
 	}
 	else
 	{
@@ -727,14 +716,7 @@ WRITE8_MEMBER(tnzs_state::kageki_csport_w)
 	}
 }
 
-WRITE8_MEMBER(tnzs_state::kabukiz_sound_bank_w)
-{
-	// to avoid the write when the sound chip is initialized
-	if (data != 0xff)
-		m_audiobank->set_entry(data & 0x07);
-}
-
-static ADDRESS_MAP_START( main_map, AS_PROGRAM, 8, tnzs_state )
+static ADDRESS_MAP_START( main_map, AS_PROGRAM, 8, tnzs_base_state )
 	AM_RANGE(0x0000, 0x7fff) AM_ROM
 	AM_RANGE(0x8000, 0xbfff) AM_DEVICE("mainbank", address_map_bank_device, amap8)
 	AM_RANGE(0xc000, 0xcfff) AM_RAM AM_DEVREADWRITE("spritegen", seta001_device, spritecodelow_r8, spritecodelow_w8)
@@ -743,14 +725,18 @@ static ADDRESS_MAP_START( main_map, AS_PROGRAM, 8, tnzs_state )
 	AM_RANGE(0xf000, 0xf2ff) AM_RAM AM_DEVREADWRITE("spritegen", seta001_device, spriteylow_r8, spriteylow_w8)
 	AM_RANGE(0xf300, 0xf303) AM_MIRROR(0xfc) AM_DEVWRITE("spritegen", seta001_device, spritectrl_w8)  /* control registers (0x80 mirror used by Arkanoid 2) */
 	AM_RANGE(0xf400, 0xf400) AM_DEVWRITE("spritegen", seta001_device, spritebgflag_w8)   /* enable / disable background transparency */
-	AM_RANGE(0xf600, 0xf600) AM_READNOP AM_WRITE(tnzs_ramrom_bankswitch_w)
+	AM_RANGE(0xf600, 0xf600) AM_READNOP AM_WRITE(ramrom_bankswitch_w)
+	AM_RANGE(0xf800, 0xfbff) AM_RAM_DEVWRITE("palette", palette_device, write) AM_SHARE("palette")
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( prompal_main_map, AS_PROGRAM, 8, extrmatn_state )
 	/* arknoid2, extrmatn, plumppop and drtoppel have PROMs instead of RAM */
 	/* drtoppel writes here anyway! (maybe leftover from tests during development) */
-	/* so the handler is patched out in init_drtopple() */
-	AM_RANGE(0xf800, 0xfbff) AM_RAM_DEVWRITE("palette", palette_device, write) AM_SHARE("palette")
+	AM_RANGE(0xf800, 0xfbff) AM_WRITENOP
+	AM_IMPORT_FROM(main_map)
 ADDRESS_MAP_END
 
-static ADDRESS_MAP_START( cpu0_type2, AS_PROGRAM, 8, tnzs_state )
+static ADDRESS_MAP_START( tnzsb_main_map, AS_PROGRAM, 8, tnzsb_state )
 	AM_RANGE(0x0000, 0x7fff) AM_ROM
 	AM_RANGE(0x8000, 0xbfff) AM_DEVICE("mainbank", address_map_bank_device, amap8)
 	AM_RANGE(0xc000, 0xcfff) AM_RAM AM_DEVREADWRITE("spritegen", seta001_device, spritecodelow_r8, spritecodelow_w8)
@@ -759,102 +745,100 @@ static ADDRESS_MAP_START( cpu0_type2, AS_PROGRAM, 8, tnzs_state )
 	AM_RANGE(0xf000, 0xf2ff) AM_RAM AM_DEVREADWRITE("spritegen", seta001_device, spriteylow_r8, spriteylow_w8)
 	AM_RANGE(0xf300, 0xf303) AM_MIRROR(0xfc) AM_DEVWRITE("spritegen", seta001_device, spritectrl_w8) /* control registers (0x80 mirror used by Arkanoid 2) */
 	AM_RANGE(0xf400, 0xf400) AM_DEVWRITE("spritegen", seta001_device, spritebgflag_w8)   /* enable / disable background transparency */
-	AM_RANGE(0xf600, 0xf600) AM_WRITE(tnzs_ramrom_bankswitch_w)
+	AM_RANGE(0xf600, 0xf600) AM_WRITE(ramrom_bankswitch_w)
 	/* kabukiz still writes here but it's not used (it's paletteram in type1 map) */
 	AM_RANGE(0xf800, 0xfbff) AM_WRITENOP
 ADDRESS_MAP_END
 
-
-static ADDRESS_MAP_START( sub_map, AS_PROGRAM, 8, tnzs_state )
+static ADDRESS_MAP_START( base_sub_map, AS_PROGRAM, 8, tnzs_base_state )
 	AM_RANGE(0x0000, 0x7fff) AM_ROM
 	AM_RANGE(0x8000, 0x9fff) AM_ROMBANK("subbank")
-	AM_RANGE(0xa000, 0xa000) AM_WRITE(tnzs_bankswitch1_w)
+	AM_RANGE(0xa000, 0xa000) AM_WRITE(bankswitch1_w)
 	AM_RANGE(0xb000, 0xb001) AM_DEVREADWRITE("ymsnd", ym2203_device, read, write)
-	AM_RANGE(0xc000, 0xc001) AM_READWRITE(tnzs_mcu_r, tnzs_mcu_w)   /* not present in insectx */
 	AM_RANGE(0xd000, 0xdfff) AM_RAM
 	AM_RANGE(0xe000, 0xefff) AM_RAM AM_SHARE("share1")
-	AM_RANGE(0xf000, 0xf003) AM_READ(arknoid2_sh_f000_r)    /* paddles in arkanoid2/plumppop. The ports are */
-						/* read but not used by the other games, and are not read at */
-						/* all by insectx. */
 ADDRESS_MAP_END
 
-static ADDRESS_MAP_START( kageki_sub_map, AS_PROGRAM, 8, tnzs_state )
-	AM_RANGE(0x0000, 0x7fff) AM_ROM
-	AM_RANGE(0x8000, 0x9fff) AM_ROMBANK("subbank")
-	AM_RANGE(0xa000, 0xa000) AM_WRITE(tnzs_bankswitch1_w)
-	AM_RANGE(0xb000, 0xb001) AM_DEVREADWRITE("ymsnd", ym2203_device, read, write)
+static ADDRESS_MAP_START( tnzs_sub_map, AS_PROGRAM, 8, tnzs_mcu_state )
+	AM_RANGE(0xc000, 0xc001) AM_READWRITE(mcu_r, mcu_w)   /* not present in insectx */
+	AM_RANGE(0xa000, 0xa000) AM_WRITE(bankswitch1_w)
+	AM_RANGE(0xf000, 0xf003) AM_READ(analog_r) /* paddles in arkanoid2/plumppop. The ports are */
+											   /* read but not used by the other games, and are not read at */
+											   /* all by insectx. */
+	AM_IMPORT_FROM(base_sub_map)
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( arknoid2_sub_map, AS_PROGRAM, 8, arknoid2_state )
+	AM_RANGE(0xc000, 0xc001) AM_READWRITE(mcu_r, mcu_w)
+	AM_IMPORT_FROM(tnzs_sub_map)
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( kageki_sub_map, AS_PROGRAM, 8, kageki_state )
 	AM_RANGE(0xc000, 0xc000) AM_READ_PORT("IN0")
 	AM_RANGE(0xc001, 0xc001) AM_READ_PORT("IN1")
 	AM_RANGE(0xc002, 0xc002) AM_READ_PORT("IN2")
-	AM_RANGE(0xd000, 0xdfff) AM_RAM
-	AM_RANGE(0xe000, 0xefff) AM_RAM AM_SHARE("share1")
+	AM_IMPORT_FROM(base_sub_map)
 ADDRESS_MAP_END
 
-/* the later board is different, it has a third CPU (and of course no mcu) */
+static ADDRESS_MAP_START( insectx_sub_map, AS_PROGRAM, 8, insectx_state )
+	AM_RANGE(0xc000, 0xc000) AM_READ_PORT("IN0")
+	AM_RANGE(0xc001, 0xc001) AM_READ_PORT("IN1")
+	AM_RANGE(0xc002, 0xc002) AM_READ_PORT("IN2")
+	AM_IMPORT_FROM(base_sub_map)
+ADDRESS_MAP_END
 
-WRITE8_MEMBER(tnzs_state::tnzsb_sound_command_w)
-{
-	m_soundlatch->write(space, offset, data);
-	m_audiocpu->set_input_line_and_vector(0, HOLD_LINE, 0xff);
-}
+/* the later board is different, it has a third CPU (and of course no mcu) */
 
-static ADDRESS_MAP_START( tnzsb_cpu1_map, AS_PROGRAM, 8, tnzs_state )
+static ADDRESS_MAP_START( tnzsb_base_sub_map, AS_PROGRAM, 8, tnzsb_state )
 	AM_RANGE(0x0000, 0x7fff) AM_ROM
 	AM_RANGE(0x8000, 0x9fff) AM_ROMBANK("subbank")
-	AM_RANGE(0xa000, 0xa000) AM_WRITE(tnzs_bankswitch1_w)
+	AM_RANGE(0xa000, 0xa000) AM_WRITE(bankswitch1_w)
 	AM_RANGE(0xb002, 0xb002) AM_READ_PORT("DSWA")
 	AM_RANGE(0xb003, 0xb003) AM_READ_PORT("DSWB")
-	AM_RANGE(0xb004, 0xb004) AM_WRITE(tnzsb_sound_command_w)
+	AM_RANGE(0xb004, 0xb004) AM_WRITE(sound_command_w)
 	AM_RANGE(0xc000, 0xc000) AM_READ_PORT("IN0")
 	AM_RANGE(0xc001, 0xc001) AM_READ_PORT("IN1")
 	AM_RANGE(0xc002, 0xc002) AM_READ_PORT("IN2")
 	AM_RANGE(0xd000, 0xdfff) AM_RAM
 	AM_RANGE(0xe000, 0xefff) AM_RAM AM_SHARE("share1")
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( tnzsb_sub_map, AS_PROGRAM, 8, tnzsb_state )
 	AM_RANGE(0xf000, 0xf003) AM_READONLY
 	AM_RANGE(0xf000, 0xf3ff) AM_RAM_DEVWRITE("palette", palette_device, write) AM_SHARE("palette")
+	AM_IMPORT_FROM(tnzsb_base_sub_map)
 ADDRESS_MAP_END
 
-static ADDRESS_MAP_START( kabukiz_cpu1_map, AS_PROGRAM, 8, tnzs_state )
-	AM_RANGE(0x0000, 0x7fff) AM_ROM
-	AM_RANGE(0x8000, 0x9fff) AM_ROMBANK("subbank")
-	AM_RANGE(0xa000, 0xa000) AM_WRITE(tnzs_bankswitch1_w)
-	AM_RANGE(0xb002, 0xb002) AM_READ_PORT("DSWA")
-	AM_RANGE(0xb003, 0xb003) AM_READ_PORT("DSWB")
-	AM_RANGE(0xb004, 0xb004) AM_WRITE(tnzsb_sound_command_w)
-	AM_RANGE(0xc000, 0xc000) AM_READ_PORT("IN0")
-	AM_RANGE(0xc001, 0xc001) AM_READ_PORT("IN1")
-	AM_RANGE(0xc002, 0xc002) AM_READ_PORT("IN2")
-	AM_RANGE(0xd000, 0xdfff) AM_RAM
-	AM_RANGE(0xe000, 0xefff) AM_RAM AM_SHARE("share1")
+static ADDRESS_MAP_START( kabukiz_sub_map, AS_PROGRAM, 8, kabukiz_state )
 	AM_RANGE(0xf800, 0xfbff) AM_RAM_DEVWRITE("palette", palette_device, write) AM_SHARE("palette")
+	AM_IMPORT_FROM(tnzsb_base_sub_map)
 ADDRESS_MAP_END
 
-static ADDRESS_MAP_START( tnzsb_cpu2_map, AS_PROGRAM, 8, tnzs_state )
+static ADDRESS_MAP_START( tnzsb_cpu2_map, AS_PROGRAM, 8, tnzsb_state )
 	AM_RANGE(0x0000, 0x7fff) AM_ROM
 	AM_RANGE(0xc000, 0xdfff) AM_RAM
 ADDRESS_MAP_END
 
-static ADDRESS_MAP_START( kabukiz_cpu2_map, AS_PROGRAM, 8, tnzs_state )
+static ADDRESS_MAP_START( kabukiz_cpu2_map, AS_PROGRAM, 8, kabukiz_state )
 	AM_RANGE(0x0000, 0x7fff) AM_ROM
 	AM_RANGE(0x8000, 0xbfff) AM_ROMBANK("audiobank")
 	AM_RANGE(0xe000, 0xffff) AM_RAM
 ADDRESS_MAP_END
 
-static ADDRESS_MAP_START( tnzsb_io_map, AS_IO, 8, tnzs_state )
+static ADDRESS_MAP_START( tnzsb_io_map, AS_IO, 8, tnzsb_state )
 	ADDRESS_MAP_GLOBAL_MASK(0xff)
 	AM_RANGE(0x00, 0x01) AM_DEVREADWRITE("ymsnd", ym2203_device, read, write)
 	AM_RANGE(0x02, 0x02) AM_DEVREAD("soundlatch", generic_latch_8_device, read)
 ADDRESS_MAP_END
 
-static ADDRESS_MAP_START( i8742_io_map, AS_IO, 8, tnzs_state )
-	AM_RANGE(MCS48_PORT_P1, MCS48_PORT_P1) AM_READ(tnzs_port1_r)
-	AM_RANGE(MCS48_PORT_P2, MCS48_PORT_P2) AM_READWRITE(tnzs_port2_r, tnzs_port2_w)
+static ADDRESS_MAP_START( i8742_map, AS_IO, 8, tnzs_mcu_state )
+	AM_RANGE(MCS48_PORT_P1, MCS48_PORT_P1) AM_READ(mcu_port1_r)
+	AM_RANGE(MCS48_PORT_P2, MCS48_PORT_P2) AM_READWRITE(mcu_port2_r, mcu_port2_w)
 	AM_RANGE(MCS48_PORT_T0, MCS48_PORT_T0) AM_READ_PORT("COIN1")
 	AM_RANGE(MCS48_PORT_T1, MCS48_PORT_T1) AM_READ_PORT("COIN2")
 ADDRESS_MAP_END
 
-
-static ADDRESS_MAP_START( jpopnics_main_map, AS_PROGRAM, 8, tnzs_state )
+static ADDRESS_MAP_START( jpopnics_main_map, AS_PROGRAM, 8, jpopnics_state )
 	AM_RANGE(0x0000, 0x7fff) AM_ROM
 	AM_RANGE(0x8000, 0xbfff) AM_DEVICE("mainbank", address_map_bank_device, amap8)
 	AM_RANGE(0xc000, 0xcfff) AM_RAM AM_DEVREADWRITE("spritegen", seta001_device, spritecodelow_r8, spritecodelow_w8)
@@ -863,21 +847,15 @@ static ADDRESS_MAP_START( jpopnics_main_map, AS_PROGRAM, 8, tnzs_state )
 	AM_RANGE(0xf000, 0xf2ff) AM_RAM AM_DEVREADWRITE("spritegen", seta001_device, spriteylow_r8, spriteylow_w8)
 	AM_RANGE(0xf300, 0xf303) AM_MIRROR(0xfc) AM_DEVWRITE("spritegen", seta001_device, spritectrl_w8) /* control registers (0x80 mirror used by Arkanoid 2) */
 	AM_RANGE(0xf400, 0xf400) AM_DEVWRITE("spritegen", seta001_device, spritebgflag_w8)   /* enable / disable background transparency */
-	AM_RANGE(0xf600, 0xf600) AM_READNOP AM_WRITE(tnzs_ramrom_bankswitch_w)
+	AM_RANGE(0xf600, 0xf600) AM_READNOP AM_WRITE(ramrom_bankswitch_w)
 	AM_RANGE(0xf800, 0xffff) AM_RAM_DEVWRITE("palette", palette_device, write) AM_SHARE("palette")
 ADDRESS_MAP_END
 
-WRITE8_MEMBER(tnzs_state::jpopnics_subbankswitch_w)
-{
-	/* bits 0-1 select ROM bank */
-	m_subbank->set_entry(data & 0x03);
-}
-
-static ADDRESS_MAP_START( jpopnics_sub_map, AS_PROGRAM, 8, tnzs_state )
+static ADDRESS_MAP_START( jpopnics_sub_map, AS_PROGRAM, 8, jpopnics_state )
 	AM_RANGE(0x0000, 0x7fff) AM_ROM
 	AM_RANGE(0x8000, 0x9fff) AM_ROMBANK("subbank")
 
-	AM_RANGE(0xa000, 0xa000) AM_WRITE(jpopnics_subbankswitch_w)
+	AM_RANGE(0xa000, 0xa000) AM_WRITE(subbankswitch_w)
 	AM_RANGE(0xb000, 0xb001) AM_DEVREADWRITE("ymsnd", ym2151_device, read, write)
 	AM_RANGE(0xc000, 0xc000) AM_READ_PORT("IN1")
 	AM_RANGE(0xc001, 0xc001) AM_READ_PORT("IN2")
@@ -887,11 +865,11 @@ static ADDRESS_MAP_START( jpopnics_sub_map, AS_PROGRAM, 8, tnzs_state )
 	AM_RANGE(0xd000, 0xdfff) AM_RAM
 	AM_RANGE(0xe000, 0xefff) AM_RAM AM_SHARE("share1")
 
-	AM_RANGE(0xf000, 0xf003) AM_READ(arknoid2_sh_f000_r)
+	AM_RANGE(0xf000, 0xf003) AM_READ(analog_r)
 ADDRESS_MAP_END
 
 /* RAM/ROM bank that maps at 0x8000-0xbfff on maincpu */
-static ADDRESS_MAP_START( mainbank_map, AS_PROGRAM, 8, tnzs_state )
+static ADDRESS_MAP_START( mainbank_map, AS_PROGRAM, 8, tnzs_base_state )
 	AM_RANGE(0x00000, 0x07fff) AM_RAM // instead of the first two banks of ROM being repeated redundantly the hardware maps RAM here
 	AM_RANGE(0x08000, 0x1ffff) AM_ROM AM_REGION(":maincpu", 0x8000)
 ADDRESS_MAP_END
@@ -1531,192 +1509,95 @@ static GFXDECODE_START( insectx )
 	GFXDECODE_ENTRY( "gfx1", 0, insectx_charlayout, 0, 32 )
 GFXDECODE_END
 
-
-/* handler called by the 2203 emulator when the internal timers cause an IRQ */
-WRITE_LINE_MEMBER(tnzs_state::irqhandler)
-{
-	m_audiocpu->set_input_line(INPUT_LINE_NMI, state ? ASSERT_LINE : CLEAR_LINE);
-}
-
-static MACHINE_CONFIG_START( arknoid2, tnzs_state )
-
+static MACHINE_CONFIG_START( tnzs_base, tnzs_base_state )
 	/* basic machine hardware */
-	MCFG_CPU_ADD("maincpu", Z80, XTAL_12MHz/2)  /* verified on pcb */
+	MCFG_CPU_ADD("maincpu", Z80,XTAL_12MHz/2)       /* 6.0 MHz ??? - Main board Crystal is 12MHz, verified on insectx, kageki, tnzsb */
 	MCFG_CPU_PROGRAM_MAP(main_map)
-	MCFG_CPU_VBLANK_INT_DRIVER("screen", tnzs_state,  arknoid2_interrupt)
+	MCFG_CPU_VBLANK_INT_DRIVER("screen", tnzs_base_state,  irq0_line_hold)
 
-	MCFG_CPU_ADD("sub", Z80, XTAL_12MHz/2)  /* verified on pcb */
-	MCFG_CPU_PROGRAM_MAP(sub_map)
-	MCFG_CPU_VBLANK_INT_DRIVER("screen", tnzs_state,  irq0_line_hold)
+	MCFG_CPU_ADD("sub", Z80,XTAL_12MHz/2)       /* 6.0 MHz ??? - Main board Crystal is 12MHz, verified on insectx, kageki, tnzsb */
+	MCFG_CPU_PROGRAM_MAP(base_sub_map)
+	MCFG_CPU_VBLANK_INT_DRIVER("screen", tnzs_base_state,  irq0_line_hold)
 
 	MCFG_FRAGMENT_ADD(tnzs_mainbank)
 
 	MCFG_QUANTUM_PERFECT_CPU("maincpu")
 
-	MCFG_MACHINE_START_OVERRIDE(tnzs_state,tnzs)
-	MCFG_MACHINE_RESET_OVERRIDE(tnzs_state,tnzs)
-
-	MCFG_DEVICE_ADD("spritegen", SETA001_SPRITE, 0)
-	MCFG_SETA001_SPRITE_GFXDECODE("gfxdecode")
-
 	/* video hardware */
-	MCFG_SCREEN_ADD("screen", RASTER)
-	MCFG_SCREEN_REFRESH_RATE(60)
-	MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
-	MCFG_SCREEN_SIZE(32*8, 32*8)
-	MCFG_SCREEN_VISIBLE_AREA(0*8, 32*8-1, 2*8, 30*8-1)
-	MCFG_SCREEN_UPDATE_DRIVER(tnzs_state, screen_update_tnzs)
-	MCFG_SCREEN_VBLANK_DRIVER(tnzs_state, screen_eof_tnzs)
-	MCFG_SCREEN_PALETTE("palette")
-
-	MCFG_GFXDECODE_ADD("gfxdecode", "palette", tnzs)
-	MCFG_PALETTE_ADD("palette", 512)
-	MCFG_PALETTE_FORMAT(xRRRRRGGGGGBBBBB)
-
-	MCFG_PALETTE_INIT_OWNER(tnzs_state,arknoid2)
-
-	/* sound hardware */
-	MCFG_SPEAKER_STANDARD_MONO("speaker")
-
-	MCFG_SOUND_ADD("ymsnd", YM2203, XTAL_12MHz/4) /* verified on pcb */
-	MCFG_AY8910_PORT_A_READ_CB(IOPORT("DSWA"))
-	MCFG_AY8910_PORT_B_READ_CB(IOPORT("DSWB"))
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "speaker", 0.3)
-MACHINE_CONFIG_END
-
-
-static MACHINE_CONFIG_START( drtoppel, tnzs_state )
-
-	/* basic machine hardware */
-	MCFG_CPU_ADD("maincpu", Z80,XTAL_12MHz/2)       /* 6.0 MHz ??? - Main board Crystal is 12MHz */
-	MCFG_CPU_PROGRAM_MAP(main_map)
-	MCFG_CPU_VBLANK_INT_DRIVER("screen", tnzs_state,  arknoid2_interrupt)
-
-	MCFG_CPU_ADD("sub", Z80,XTAL_12MHz/2)       /* 6.0 MHz ??? - Main board Crystal is 12MHz */
-	MCFG_CPU_PROGRAM_MAP(sub_map)
-	MCFG_CPU_VBLANK_INT_DRIVER("screen", tnzs_state,  irq0_line_hold)
-
-	MCFG_FRAGMENT_ADD(tnzs_mainbank)
-
-	MCFG_QUANTUM_PERFECT_CPU("maincpu")
-
-	MCFG_MACHINE_START_OVERRIDE(tnzs_state,tnzs)
-	MCFG_MACHINE_RESET_OVERRIDE(tnzs_state,tnzs)
-
 	MCFG_DEVICE_ADD("spritegen", SETA001_SPRITE, 0)
 	MCFG_SETA001_SPRITE_GFXDECODE("gfxdecode")
 
-	/* video hardware */
 	MCFG_SCREEN_ADD("screen", RASTER)
 	MCFG_SCREEN_REFRESH_RATE(60)
 	MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
 	MCFG_SCREEN_SIZE(32*8, 32*8)
 	MCFG_SCREEN_VISIBLE_AREA(0*8, 32*8-1, 2*8, 30*8-1)
-	MCFG_SCREEN_UPDATE_DRIVER(tnzs_state, screen_update_tnzs)
-	MCFG_SCREEN_VBLANK_DRIVER(tnzs_state, screen_eof_tnzs)
+	MCFG_SCREEN_UPDATE_DRIVER(tnzs_base_state, screen_update_tnzs)
+	MCFG_SCREEN_VBLANK_DRIVER(tnzs_base_state, screen_eof_tnzs)
 	MCFG_SCREEN_PALETTE("palette")
 
 	MCFG_GFXDECODE_ADD("gfxdecode", "palette", tnzs)
 	MCFG_PALETTE_ADD("palette", 512)
 	MCFG_PALETTE_FORMAT(xRRRRRGGGGGBBBBB)
-	MCFG_PALETTE_INIT_OWNER(tnzs_state,arknoid2)
 
 	/* sound hardware */
 	MCFG_SPEAKER_STANDARD_MONO("speaker")
-
-	MCFG_SOUND_ADD("ymsnd", YM2203, XTAL_12MHz/4)
-	MCFG_AY8910_PORT_A_READ_CB(IOPORT("DSWA"))
-	MCFG_AY8910_PORT_B_READ_CB(IOPORT("DSWB"))
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "speaker", 0.3)
 MACHINE_CONFIG_END
 
-
-static MACHINE_CONFIG_START( tnzs, tnzs_state )
-
-	/* basic machine hardware */
-	MCFG_CPU_ADD("maincpu", Z80,XTAL_12MHz/2)       /* 6.0 MHz ??? - Main board Crystal is 12MHz */
-	MCFG_CPU_PROGRAM_MAP(main_map)
-	MCFG_CPU_VBLANK_INT_DRIVER("screen", tnzs_state,  irq0_line_hold)
-
-	MCFG_CPU_ADD("sub", Z80,XTAL_12MHz/2)       /* 6.0 MHz ??? - Main board Crystal is 12MHz */
-	MCFG_CPU_PROGRAM_MAP(sub_map)
-	MCFG_CPU_VBLANK_INT_DRIVER("screen", tnzs_state,  irq0_line_hold)
-
+static MACHINE_CONFIG_DERIVED_CLASS( tnzs, tnzs_base, tnzs_state )
 	MCFG_CPU_ADD("mcu", I8742, 12000000/2)  /* 400KHz ??? - Main board Crystal is 12MHz */
-	MCFG_CPU_IO_MAP(i8742_io_map)
-
-	MCFG_FRAGMENT_ADD(tnzs_mainbank)
-
-	MCFG_QUANTUM_PERFECT_CPU("maincpu")
+	MCFG_CPU_IO_MAP(i8742_map)
 
-	MCFG_MACHINE_START_OVERRIDE(tnzs_state,tnzs)
-	MCFG_MACHINE_RESET_OVERRIDE(tnzs_state,tnzs)
-
-	MCFG_DEVICE_ADD("spritegen", SETA001_SPRITE, 0)
-	MCFG_SETA001_SPRITE_GFXDECODE("gfxdecode")
+	MCFG_CPU_MODIFY("sub")
+	MCFG_CPU_PROGRAM_MAP(tnzs_sub_map)
 
 	/* video hardware */
-	MCFG_SCREEN_ADD("screen", RASTER)
+	MCFG_SCREEN_MODIFY("screen")
 	MCFG_SCREEN_REFRESH_RATE(59.15)   /* it should be the same as the newer pcb vsync */
 	MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500) /* not accurate */)
-	MCFG_SCREEN_SIZE(32*8, 32*8)
-	MCFG_SCREEN_VISIBLE_AREA(0*8, 32*8-1, 2*8, 30*8-1)
-	MCFG_SCREEN_UPDATE_DRIVER(tnzs_state, screen_update_tnzs)
-	MCFG_SCREEN_VBLANK_DRIVER(tnzs_state, screen_eof_tnzs)
-	MCFG_SCREEN_PALETTE("palette")
-
-	MCFG_GFXDECODE_ADD("gfxdecode", "palette", tnzs)
-	MCFG_PALETTE_ADD("palette", 512)
-	MCFG_PALETTE_FORMAT(xRRRRRGGGGGBBBBB)
 
 	/* sound hardware */
-	MCFG_SPEAKER_STANDARD_MONO("speaker")
-
 	MCFG_SOUND_ADD("ymsnd", YM2203, XTAL_12MHz/4)
 	MCFG_AY8910_PORT_A_READ_CB(IOPORT("DSWA"))
 	MCFG_AY8910_PORT_B_READ_CB(IOPORT("DSWB"))
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "speaker", 0.3)
 MACHINE_CONFIG_END
 
-
-static MACHINE_CONFIG_START( insectx, tnzs_state )
-
+static MACHINE_CONFIG_DERIVED_CLASS( extrmatn, tnzs, extrmatn_state )
 	/* basic machine hardware */
-	MCFG_CPU_ADD("maincpu", Z80, XTAL_12MHz/2)  /* verified on pcb */
-	MCFG_CPU_PROGRAM_MAP(main_map)
-	MCFG_CPU_VBLANK_INT_DRIVER("screen", tnzs_state,  irq0_line_hold)
+	MCFG_CPU_MODIFY("maincpu")
+	MCFG_CPU_PROGRAM_MAP(prompal_main_map)
 
-	MCFG_CPU_ADD("sub", Z80, XTAL_12MHz/2)  /* verified on pcb */
-	MCFG_CPU_PROGRAM_MAP(sub_map)
-	MCFG_CPU_VBLANK_INT_DRIVER("screen", tnzs_state,  irq0_line_hold)
+	/* video hardware */
+	MCFG_SCREEN_MODIFY("screen")
+	MCFG_SCREEN_REFRESH_RATE(60)
+	MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
 
-	MCFG_FRAGMENT_ADD(tnzs_mainbank)
+	MCFG_PALETTE_MODIFY("palette")
+	MCFG_PALETTE_INIT_OWNER(tnzs_base_state, prompalette)
+MACHINE_CONFIG_END
 
-	MCFG_QUANTUM_PERFECT_CPU("maincpu")
+static MACHINE_CONFIG_DERIVED_CLASS( arknoid2, extrmatn, arknoid2_state )
+	/* basic machine hardware */
+	MCFG_CPU_MODIFY("maincpu")
+	MCFG_CPU_VBLANK_INT_DRIVER("screen", arknoid2_state, mcu_interrupt)
 
-	MCFG_MACHINE_START_OVERRIDE(tnzs_state,tnzs)
-	MCFG_MACHINE_RESET_OVERRIDE(tnzs_state,tnzs)
+	MCFG_CPU_MODIFY("sub")
+	MCFG_CPU_PROGRAM_MAP(arknoid2_sub_map)
 
-	MCFG_DEVICE_ADD("spritegen", SETA001_SPRITE, 0)
-	MCFG_SETA001_SPRITE_GFXDECODE("gfxdecode")
+	MCFG_CPU_MODIFY("mcu")
+	MCFG_DEVICE_DISABLE()
+MACHINE_CONFIG_END
 
-	/* video hardware */
-	MCFG_SCREEN_ADD("screen", RASTER)
-	MCFG_SCREEN_REFRESH_RATE(60)
-	MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
-	MCFG_SCREEN_SIZE(32*8, 32*8)
-	MCFG_SCREEN_VISIBLE_AREA(0*8, 32*8-1, 2*8, 30*8-1)
-	MCFG_SCREEN_UPDATE_DRIVER(tnzs_state, screen_update_tnzs)
-	MCFG_SCREEN_VBLANK_DRIVER(tnzs_state, screen_eof_tnzs)
-	MCFG_SCREEN_PALETTE("palette")
+static MACHINE_CONFIG_DERIVED_CLASS( insectx, tnzs_base, insectx_state )
+	/* basic machine hardware */
+	MCFG_CPU_MODIFY("sub")
+	MCFG_CPU_PROGRAM_MAP(insectx_sub_map)
 
-	MCFG_GFXDECODE_ADD("gfxdecode", "palette", insectx)
-	MCFG_PALETTE_ADD("palette", 512)
-	MCFG_PALETTE_FORMAT(xRRRRRGGGGGBBBBB)
+	/* video hardware */
+	MCFG_GFXDECODE_MODIFY("gfxdecode", insectx)
 
 	/* sound hardware */
-	MCFG_SPEAKER_STANDARD_MONO("speaker")
-
 	MCFG_SOUND_ADD("ymsnd", YM2203, XTAL_12MHz/4) /* verified on pcb */
 	MCFG_AY8910_PORT_A_READ_CB(IOPORT("DSWA"))
 	MCFG_AY8910_PORT_B_READ_CB(IOPORT("DSWB"))
@@ -1724,47 +1605,15 @@ static MACHINE_CONFIG_START( insectx, tnzs_state )
 MACHINE_CONFIG_END
 
 
-static MACHINE_CONFIG_START( kageki, tnzs_state )
-
+static MACHINE_CONFIG_DERIVED_CLASS( kageki, tnzs_base, kageki_state )
 	/* basic machine hardware */
-	MCFG_CPU_ADD("maincpu", Z80, XTAL_12MHz/2) /* verified on pcb */
-	MCFG_CPU_PROGRAM_MAP(main_map)
-	MCFG_CPU_VBLANK_INT_DRIVER("screen", tnzs_state,  irq0_line_hold)
-
-	MCFG_CPU_ADD("sub", Z80, XTAL_12MHz/2) /* verified on pcb */
+	MCFG_CPU_MODIFY("sub")
 	MCFG_CPU_PROGRAM_MAP(kageki_sub_map)
-	MCFG_CPU_VBLANK_INT_DRIVER("screen", tnzs_state,  irq0_line_hold)
-
-	MCFG_FRAGMENT_ADD(tnzs_mainbank)
-
-	MCFG_QUANTUM_PERFECT_CPU("maincpu")
-
-	MCFG_MACHINE_START_OVERRIDE(tnzs_state,tnzs)
-	MCFG_MACHINE_RESET_OVERRIDE(tnzs_state,tnzs)
-
-	MCFG_DEVICE_ADD("spritegen", SETA001_SPRITE, 0)
-	MCFG_SETA001_SPRITE_GFXDECODE("gfxdecode")
-
-	/* video hardware */
-	MCFG_SCREEN_ADD("screen", RASTER)
-	MCFG_SCREEN_REFRESH_RATE(60)
-	MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
-	MCFG_SCREEN_SIZE(32*8, 32*8)
-	MCFG_SCREEN_VISIBLE_AREA(0*8, 32*8-1, 2*8, 30*8-1)
-	MCFG_SCREEN_UPDATE_DRIVER(tnzs_state, screen_update_tnzs)
-	MCFG_SCREEN_VBLANK_DRIVER(tnzs_state, screen_eof_tnzs)
-	MCFG_SCREEN_PALETTE("palette")
-
-	MCFG_GFXDECODE_ADD("gfxdecode", "palette", tnzs)
-	MCFG_PALETTE_ADD("palette", 512)
-	MCFG_PALETTE_FORMAT(xRRRRRGGGGGBBBBB)
 
 	/* sound hardware */
-	MCFG_SPEAKER_STANDARD_MONO("speaker")
-
 	MCFG_SOUND_ADD("ymsnd", YM2203, XTAL_12MHz/4) /* verified on pcb */
-	MCFG_AY8910_PORT_A_READ_CB(READ8(tnzs_state, kageki_csport_r))
-	MCFG_AY8910_PORT_B_WRITE_CB(WRITE8(tnzs_state, kageki_csport_w))
+	MCFG_AY8910_PORT_A_READ_CB(READ8(kageki_state, csport_r))
+	MCFG_AY8910_PORT_B_WRITE_CB(WRITE8(kageki_state, csport_w))
 	MCFG_SOUND_ROUTE(0, "speaker", 0.15)
 	MCFG_SOUND_ROUTE(1, "speaker", 0.15)
 	MCFG_SOUND_ROUTE(2, "speaker", 0.15)
@@ -1772,57 +1621,31 @@ static MACHINE_CONFIG_START( kageki, tnzs_state )
 
 	MCFG_SOUND_ADD("samples", SAMPLES, 0)
 	MCFG_SAMPLES_CHANNELS(1)
-	MCFG_SAMPLES_START_CB(tnzs_state, kageki_init_samples)
+	MCFG_SAMPLES_START_CB(kageki_state, init_samples)
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "speaker", 1.0)
 MACHINE_CONFIG_END
 
-
-static MACHINE_CONFIG_START( tnzsb, tnzs_state )
-
+static MACHINE_CONFIG_DERIVED_CLASS( tnzsb, tnzs_base, tnzsb_state )
 	/* basic machine hardware */
-	MCFG_CPU_ADD("maincpu", Z80, XTAL_12MHz/2) /* verified on pcb */
-	MCFG_CPU_PROGRAM_MAP(cpu0_type2)
-	MCFG_CPU_VBLANK_INT_DRIVER("screen", tnzs_state,  irq0_line_hold)
+	MCFG_CPU_MODIFY("maincpu")
+	MCFG_CPU_PROGRAM_MAP(tnzsb_main_map)
 
-	MCFG_CPU_ADD("sub", Z80, XTAL_12MHz/2) /* verified on pcb */
-	MCFG_CPU_PROGRAM_MAP(tnzsb_cpu1_map)
-	MCFG_CPU_VBLANK_INT_DRIVER("screen", tnzs_state,  irq0_line_hold)
+	MCFG_CPU_MODIFY("sub") /* verified on pcb */
+	MCFG_CPU_PROGRAM_MAP(tnzsb_sub_map)
 
 	MCFG_CPU_ADD("audiocpu", Z80, XTAL_12MHz/2) /* verified on pcb */
 	MCFG_CPU_PROGRAM_MAP(tnzsb_cpu2_map)
 	MCFG_CPU_IO_MAP(tnzsb_io_map)
 
-	MCFG_FRAGMENT_ADD(tnzs_mainbank)
-
-	MCFG_QUANTUM_PERFECT_CPU("maincpu")
-
-	MCFG_MACHINE_START_OVERRIDE(tnzs_state,tnzs)
-	MCFG_MACHINE_RESET_OVERRIDE(tnzs_state,tnzs)
-
-	MCFG_DEVICE_ADD("spritegen", SETA001_SPRITE, 0)
-	MCFG_SETA001_SPRITE_GFXDECODE("gfxdecode")
-
 	/* video hardware */
-	MCFG_SCREEN_ADD("screen", RASTER)
+	MCFG_SCREEN_MODIFY("screen")
 	MCFG_SCREEN_REFRESH_RATE(59.15)   /* verified on pcb */
-	MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
-	MCFG_SCREEN_SIZE(32*8, 32*8)
-	MCFG_SCREEN_VISIBLE_AREA(0*8, 32*8-1, 2*8, 30*8-1)
-	MCFG_SCREEN_UPDATE_DRIVER(tnzs_state, screen_update_tnzs)
-	MCFG_SCREEN_VBLANK_DRIVER(tnzs_state, screen_eof_tnzs)
-	MCFG_SCREEN_PALETTE("palette")
-
-	MCFG_GFXDECODE_ADD("gfxdecode", "palette", tnzs)
-	MCFG_PALETTE_ADD("palette", 512)
-	MCFG_PALETTE_FORMAT(xRRRRRGGGGGBBBBB)
 
 	/* sound hardware */
-	MCFG_SPEAKER_STANDARD_MONO("speaker")
-
 	MCFG_GENERIC_LATCH_8_ADD("soundlatch")
 
 	MCFG_SOUND_ADD("ymsnd", YM2203, XTAL_12MHz/4) /* verified on pcb */
-	MCFG_YM2203_IRQ_HANDLER(WRITELINE(tnzs_state, irqhandler))
+	MCFG_YM2203_IRQ_HANDLER(WRITELINE(tnzsb_state, ym2203_irqhandler))
 	MCFG_SOUND_ROUTE(0, "speaker", 1.0)
 	MCFG_SOUND_ROUTE(1, "speaker", 1.0)
 	MCFG_SOUND_ROUTE(2, "speaker", 1.0)
@@ -1830,17 +1653,18 @@ static MACHINE_CONFIG_START( tnzsb, tnzs_state )
 MACHINE_CONFIG_END
 
 
-static MACHINE_CONFIG_DERIVED( kabukiz, tnzsb )
+static MACHINE_CONFIG_DERIVED_CLASS( kabukiz, tnzsb, kabukiz_state )
 
 	/* basic machine hardware */
 	MCFG_CPU_MODIFY("sub")
-	MCFG_CPU_PROGRAM_MAP(kabukiz_cpu1_map)
+	MCFG_CPU_PROGRAM_MAP(kabukiz_sub_map)
 
 	MCFG_CPU_MODIFY("audiocpu")
 	MCFG_CPU_PROGRAM_MAP(kabukiz_cpu2_map)
 
+	/* sound hardware */
 	MCFG_SOUND_MODIFY("ymsnd")
-	MCFG_AY8910_PORT_A_WRITE_CB(WRITE8(tnzs_state, kabukiz_sound_bank_w))
+	MCFG_AY8910_PORT_A_WRITE_CB(WRITE8(kabukiz_state, sound_bank_w))
 	MCFG_AY8910_PORT_B_WRITE_CB(DEVWRITE8("dac", dac_byte_interface, write))
 
 	MCFG_SOUND_ADD("dac", DAC_8BIT_R2R, 0) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "speaker", 0.5) // unknown DAC
@@ -1849,49 +1673,75 @@ static MACHINE_CONFIG_DERIVED( kabukiz, tnzsb )
 MACHINE_CONFIG_END
 
 
-static MACHINE_CONFIG_START( jpopnics, tnzs_state )
-
+static MACHINE_CONFIG_DERIVED_CLASS( jpopnics, tnzs_base, jpopnics_state )
 	/* basic machine hardware */
-	MCFG_CPU_ADD("maincpu", Z80,XTAL_12MHz/2) /* Not verified - Main board Crystal is 12MHz */
+	MCFG_CPU_MODIFY("maincpu")
 	MCFG_CPU_PROGRAM_MAP(jpopnics_main_map)
-	MCFG_CPU_VBLANK_INT_DRIVER("screen", tnzs_state,  irq0_line_hold)
 
-	MCFG_CPU_ADD("sub", Z80,XTAL_12MHz/2)   /* Not verified - Main board Crystal is 12MHz */
+	MCFG_CPU_MODIFY("sub")
 	MCFG_CPU_PROGRAM_MAP(jpopnics_sub_map)
-	MCFG_CPU_VBLANK_INT_DRIVER("screen", tnzs_state,  irq0_line_hold)
-
-	MCFG_FRAGMENT_ADD(tnzs_mainbank)
-
-	MCFG_QUANTUM_PERFECT_CPU("maincpu")
-
-	MCFG_MACHINE_START_OVERRIDE(tnzs_state,tnzs_common)
-	MCFG_MACHINE_RESET_OVERRIDE(tnzs_state,jpopnics)
-
-	MCFG_DEVICE_ADD("spritegen", SETA001_SPRITE, 0)
-	MCFG_SETA001_SPRITE_GFXDECODE("gfxdecode")
 
 	/* video hardware */
-	MCFG_SCREEN_ADD("screen", RASTER)
-	MCFG_SCREEN_REFRESH_RATE(60)
-	MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
-	MCFG_SCREEN_SIZE(32*8, 32*8)
-	MCFG_SCREEN_VISIBLE_AREA(0*8, 32*8-1, 2*8, 30*8-1)
-	MCFG_SCREEN_UPDATE_DRIVER(tnzs_state, screen_update_tnzs)
-	MCFG_SCREEN_VBLANK_DRIVER(tnzs_state, screen_eof_tnzs)
-	MCFG_SCREEN_PALETTE("palette")
-
-	MCFG_GFXDECODE_ADD("gfxdecode", "palette", tnzs)
-	MCFG_PALETTE_ADD("palette", 1024)
+	MCFG_PALETTE_MODIFY("palette")
+	MCFG_PALETTE_ENTRIES(1024)
 	MCFG_PALETTE_FORMAT(GGGGBBBBRRRRxxxx) /* wrong, the other 4 bits seem to be used as well */
 	MCFG_PALETTE_ENDIANNESS(ENDIANNESS_BIG)
 
 	/* sound hardware */
-	MCFG_SPEAKER_STANDARD_MONO("speaker")
-
 	MCFG_YM2151_ADD("ymsnd", XTAL_12MHz/4) /* Not verified - Main board Crystal is 12MHz */
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "speaker", 0.3)
 MACHINE_CONFIG_END
 
+/***************************************************************************
+
+  PCBs
+
+***************************************************************************/
+/*  The TNZS/Seta hardware has a variety of somewhat different pcbs, all of
+    which have both Seta and Taito Part numbers.
+    All pcbs have Z80B processors and one 6264 mainram chip and an X1-001
+    and X1-002 video chip and an X1-004 I/O? Chip, and four PALs
+
+Seta#       Taito#s             CPUS    RxM2    ROM1    MCU?    Video ram   PROMs   SETA X1 GFXROMs     QUADRATURE  ESD. PROT   Games                           Picture
+P0-022-A    K1100245A J1100108A 2xZ80B  512/256 512/256 8042    4x6116      Yes, 2  03      23c1000     uPD4701AC   3x X2-003   arkanoid2, plumppop(A)          http://www.classicarcaderesource.com/RevengeOfDoh3.jpg
+P0-025-A    K1100241A J1100107A 2xZ80B  512/256 512/256 8042    4x6116      Yes, 2  03      23c1000     N/A         3x X2-003   drtoppel,extermatn,chukatai(B)  http://arcade.ym2149.com/pcb/taito/drtoppel_pcb_partside.jpg
+P0-028-A    K1100416A J1100332A 2xZ80B  512/256 512/256 8042    4x6116      No      05,06   23c1000     N/A         3x X2-004   chukatai(B)                     http://i.ebayimg.com/images/g/AhoAAOSw-FZXj5A5/s-l1600.jpg
+P0-038A     M6100309A           3xZ80B  512/256 512/256 NONE    1x6164      No      05,06   23c1000     N/A         3x X2-003   kageki                          http://i.ebayimg.com/images/a/(KGrHqJ,!lwE6C8-G97lBOjOu9mwVw~~/s-l1600.jpg
+P0-041-1    CA403001A           2xZ80B  61256   27c1000 8742    1x6164      No      05,06   27c1000     N/A         5x X2-005   tnzsop(C)                       http://arcade.ym2149.com/pcb/taito/tnzs_pcb3_partside.jpg
+P0-041-A    K1100356A J1100156A 2xZ80B  61256   27c1000 8042    1x6164      No      05,06   23c1000     N/A         5x X2-005   tnzs(j,u)o                      http://arcade.ym2149.com/pcb/taito/tnzs_pcb1_partside.jpg
+P0-043A     M6100356A           3xZ80B* 61256   27512** NONE    1x6164      No      05,06   LH534000(C) N/A         4x X2-004   tnzs(j,u), kabukiz              http://arcade.ym2149.com/pcb/taito/tnzs_pcb2_mainboard_partside.jpg
+P0-056A     K1100476A J1100201A 3xZ80B  EMPTY*3 27c1000 NONE    1x6164      No      05,06   LH534000    U43???      5x X2-005   insectx(D)                      http://www.jammarcade.net/images/2014/04/InsectorX.jpg
+
+(A) It is very likely plumppop also uses this P0-022-A PCB, as the game reads
+    the quadratures the same way as arkanoid2 does.
+    arkanoid2 only has 1 x2-003 ESD protection resistor pack populated, but the
+    PCB can have 3, the other two (for more joysticks/buttons?) are not
+    populated. arkanoid2's second maincpu socket is also empty, but this is
+    clearly not the case for plumppop.
+(B) chukatai has one set which unlike its earlier sets uses the P0-025-A
+    PCB, but with a daughterboard which converts four of the 23c1000 gfx ROM
+    sockets into 8 27c1000 eprom sockets, and DOES use color PROMs!
+    The other pcb set uses P0-028-A pcb and 23c1000 mask roms and color RAM,
+    but has lower rom id numbers. The higher numbered set  was likely created
+    by Taito to 'use up' a stock of older P0-025-A pcbs.
+(C) This is a development/prototype PCB, hence it has 32 pin sockets for the
+    gfx ROMs as 27c1000 eproms, instead of 28 pin sockets for 23c1000 mask
+    ROMs. It also uses an (unprotected?) 8742 MCU.
+    Another curious thing is the Taito ID number may have accidentally been
+    printed in backwards order, i.e should be C1100304A which fits the pattern
+    of the other boards.
+(D) InsectorX has a lot of rework on its PCB, two greenwires for each of the
+    two LH534000 mask ROMs, and four wires connected to the X1-004 I/O chip
+    pins 18, 19, 20, and 21, connecting it to 4 pins of a dip16 chip @ U43
+    with its markings sanded off. Is this chip at U43 a tiny MCU?
+*   tnzs(j,u) uses a sub board with a z80b and 23c1000 mask ROMs on it for gfx,
+    plugged into the four LH534000 mask ROM sockets and the 2nd z80 socket.
+    Like Kageki's P0-038A mainboard, this mainboard has a third z80 on it which
+    acts in place of the 8x42 mcu used by the older tnzs sets.
+**  This is a 28-pin 27512 in a 32-pin socket which alternately holds a 27c1000.
+*3  This is unpopulated, but the pcb can accept a 61256 SRAM here.
+*/
+
 
 /***************************************************************************
 
@@ -1907,8 +1757,8 @@ ROM_START( plumppop )
 	ROM_REGION( 0x10000, "sub", 0 ) /* 64k for the second CPU */
 	ROM_LOAD( "a98-11.bin", 0x00000, 0x10000, CRC(bc56775c) SHA1(0c22c22c0e9d7ec0e34f8ab4bfe61068f65e8759) )
 
-	ROM_REGION( 0x10000, "audiocpu", 0 )    /* M-Chip (i8742 internal ROM) */
-	ROM_LOAD( "plmp8742.bin", 0x0000, 0x0800, NO_DUMP )
+	ROM_REGION( 0x10000, "mcu", 0 )    /* M-Chip (i8x42 internal ROM) */
+	ROM_LOAD( "b06-14.1g", 0x0000, 0x0800, BAD_DUMP CRC(28907072) SHA1(21c7017af8a8ceb8e43d7e798f48518b136fd45c) ) /* Chip label and location is a guess, also unknown if it actually uses the same MCU as drtoppel/extrmatn, but it appears to work fine, marked as bad until verified that it uses same M-001 mcu */
 
 	ROM_REGION( 0x100000, "gfx1", 0 )
 	ROM_LOAD( "a98-01.bin", 0x00000, 0x10000, CRC(f3033dca) SHA1(130744998f0531a82de2814231dddea3ad710f60) )
@@ -1931,6 +1781,12 @@ ROM_START( plumppop )
 	ROM_REGION( 0x0400, "proms", 0 )        /* color proms */
 	ROM_LOAD( "a98-13.bpr", 0x0000, 0x200, CRC(7cde2da5) SHA1(0cccfc35fb716ebb4cffa85c75681f33ca80a56e) )   /* hi bytes, AM27S29 or compatible like MB7124 */
 	ROM_LOAD( "a98-12.bpr", 0x0200, 0x200, CRC(90dc9da7) SHA1(f719dead7f4597e5ee6f1103599505b98cb58299) )   /* lo bytes, AM27S29 or compatible like MB7124 */
+
+	ROM_REGION( 0x10000, "pal", 0 ) /* pals on plumppop are unknown, but very likely the same set as arkanoid2/extrmatn/drtoppel/chukataio/etc */
+	ROM_LOAD( "b06-10.pal16l8a.d9.jed", 0x00000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-11.pal16l8a.d6.jed", 0x01000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-12.pal16l8a.c3.jed", 0x02000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-13.pal16l8a.c2.jed", 0x03000, 0x01000, NO_DUMP)
 ROM_END
 
 ROM_START( jpopnics )
@@ -1959,8 +1815,8 @@ ROM_START( extrmatn )
 	ROM_REGION( 0x10000, "sub", 0 )             /* Region 2 - sound cpu */
 	ROM_LOAD( "b06-19.4e", 0x00000, 0x10000, CRC(8de43ed9) SHA1(53e6d8fa93889c38733d169e983f2caf1da71f43) )
 
-	ROM_REGION( 0x10000, "audiocpu", 0 )    /* M-Chip (i8742 internal ROM) */
-	ROM_LOAD( "extr8742.4f", 0x0000, 0x0800, NO_DUMP ) /* Labeled B06-14 */
+	ROM_REGION( 0x10000, "mcu", 0 )    /* M-Chip (i8x42 internal ROM) */
+	ROM_LOAD( "b06-14.1g", 0x0000, 0x0800, CRC(28907072) SHA1(21c7017af8a8ceb8e43d7e798f48518b136fd45c) ) /* Labeled B06-14 and under printed label "Taito M-001, 128P, 720100", is a mask 8042 */
 
 	ROM_REGION( 0x80000, "gfx1", 0 )
 	ROM_LOAD( "b06-01.13a", 0x00000, 0x20000, CRC(d2afbf7e) SHA1(28b4cf94798f049a9f8375464741dbef208d7290) )
@@ -1971,6 +1827,12 @@ ROM_START( extrmatn )
 	ROM_REGION( 0x0400, "proms", 0 )
 	ROM_LOAD( "b06-09.15f", 0x00000, 0x200, CRC(f388b361) SHA1(f00db6ad6994cfe9b7ad76e30b7049b11f8c16e4) )  /* hi bytes, AM27S29 or compatible like MB7124 */
 	ROM_LOAD( "b06-08.17f", 0x00200, 0x200, CRC(10c9aac3) SHA1(09d6f791dea358e78099af7a370b00b8504ffc97) )  /* lo bytes, AM27S29 or compatible like MB7124 */
+
+	ROM_REGION( 0x10000, "pal", 0 ) /* these are shared with several other games on this hardware */
+	ROM_LOAD( "b06-10.pal16l8a.d9.jed", 0x00000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-11.pal16l8a.d6.jed", 0x01000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-12.pal16l8a.c3.jed", 0x02000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-13.pal16l8a.c2.jed", 0x03000, 0x01000, NO_DUMP)
 ROM_END
 
 ROM_START( extrmatnu )
@@ -1981,8 +1843,8 @@ ROM_START( extrmatnu )
 	ROM_REGION( 0x10000, "sub", 0 )             /* Region 2 - sound cpu */
 	ROM_LOAD( "b06-22.4e", 0x00000, 0x10000, CRC(744f2c84) SHA1(7565c1594c2a3bae1ae45afcbf93363fe2b12d58) )
 
-	ROM_REGION( 0x10000, "audiocpu", 0 )    /* M-Chip (i8742 internal ROM) */
-	ROM_LOAD( "extr8742.4f", 0x0000, 0x0800, NO_DUMP ) /* Labeled B06-14 */
+	ROM_REGION( 0x10000, "mcu", 0 )    /* M-Chip (i8x42 internal ROM) */
+	ROM_LOAD( "b06-14.1g", 0x0000, 0x0800, CRC(28907072) SHA1(21c7017af8a8ceb8e43d7e798f48518b136fd45c) ) /* Labeled B06-14 and under printed label "Taito M-001, 128P, 720100", is a mask 8042 */
 
 	ROM_REGION( 0x80000, "gfx1", 0 )
 	ROM_LOAD( "b06-01.13a", 0x00000, 0x20000, CRC(d2afbf7e) SHA1(28b4cf94798f049a9f8375464741dbef208d7290) )
@@ -1993,8 +1855,13 @@ ROM_START( extrmatnu )
 	ROM_REGION( 0x0400, "proms", 0 )
 	ROM_LOAD( "b06-09.15f", 0x00000, 0x200, CRC(f388b361) SHA1(f00db6ad6994cfe9b7ad76e30b7049b11f8c16e4) )  /* hi bytes, AM27S29 or compatible like MB7124 */
 	ROM_LOAD( "b06-08.17f", 0x00200, 0x200, CRC(10c9aac3) SHA1(09d6f791dea358e78099af7a370b00b8504ffc97) )  /* lo bytes, AM27S29 or compatible like MB7124 */
-ROM_END
 
+	ROM_REGION( 0x10000, "pal", 0 ) /* these are shared with several other games on this hardware */
+	ROM_LOAD( "b06-10.pal16l8a.d9.jed", 0x00000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-11.pal16l8a.d6.jed", 0x01000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-12.pal16l8a.c3.jed", 0x02000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-13.pal16l8a.c2.jed", 0x03000, 0x01000, NO_DUMP)
+ROM_END
 
 ROM_START( extrmatnur )
 	ROM_REGION( 0x20000, "maincpu", 0 )             /* Region 0 - main cpu */
@@ -2004,8 +1871,8 @@ ROM_START( extrmatnur )
 	ROM_REGION( 0x10000, "sub", 0 )             /* Region 2 - sound cpu */
 	ROM_LOAD( "b06_17", 0x00000, 0x10000, CRC(744f2c84) SHA1(7565c1594c2a3bae1ae45afcbf93363fe2b12d58) )
 
-	ROM_REGION( 0x10000, "audiocpu", 0 )    /* M-Chip (i8742 internal ROM) */
-	ROM_LOAD( "extr8742.4f", 0x0000, 0x0800, NO_DUMP ) /* Labeled B06-14 */
+	ROM_REGION( 0x10000, "mcu", 0 )    /* M-Chip (i8x42 internal ROM) */
+	ROM_LOAD( "b06-14.1g", 0x0000, 0x0800, CRC(28907072) SHA1(21c7017af8a8ceb8e43d7e798f48518b136fd45c) ) /* Labeled B06-14 and under printed label "Taito M-001, 128P, 720100", is a mask 8042 */
 
 	ROM_REGION( 0x80000, "gfx1", 0 )
 	ROM_LOAD( "b06-01.13a", 0x00000, 0x20000, CRC(d2afbf7e) SHA1(28b4cf94798f049a9f8375464741dbef208d7290) )
@@ -2016,6 +1883,12 @@ ROM_START( extrmatnur )
 	ROM_REGION( 0x0400, "proms", 0 )
 	ROM_LOAD( "b06-09.15f", 0x00000, 0x200, CRC(f388b361) SHA1(f00db6ad6994cfe9b7ad76e30b7049b11f8c16e4) )  /* hi bytes, AM27S29 or compatible like MB7124 */
 	ROM_LOAD( "b06-08.17f", 0x00200, 0x200, CRC(10c9aac3) SHA1(09d6f791dea358e78099af7a370b00b8504ffc97) )  /* lo bytes, AM27S29 or compatible like MB7124 */
+
+	ROM_REGION( 0x10000, "pal", 0 ) /* these are shared with several other games on this hardware */
+	ROM_LOAD( "b06-10.pal16l8a.d9.jed", 0x00000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-11.pal16l8a.d6.jed", 0x01000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-12.pal16l8a.c3.jed", 0x02000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-13.pal16l8a.c2.jed", 0x03000, 0x01000, NO_DUMP)
 ROM_END
 
 ROM_START( extrmatnj )
@@ -2026,8 +1899,8 @@ ROM_START( extrmatnj )
 	ROM_REGION( 0x10000, "sub", 0 )             /* Region 2 - sound cpu */
 	ROM_LOAD( "b06-07.4e", 0x00000, 0x10000, CRC(b37fb8b3) SHA1(10696914b9e39d34d56069a69b9d641339ea2309) )
 
-	ROM_REGION( 0x10000, "audiocpu", 0 )    /* M-Chip (i8742 internal ROM) */
-	ROM_LOAD( "extr8742.4f", 0x0000, 0x0800, NO_DUMP ) /* Labeled B06-14 */
+	ROM_REGION( 0x10000, "mcu", 0 )    /* M-Chip (i8x42 internal ROM) */
+	ROM_LOAD( "b06-14.1g", 0x0000, 0x0800, CRC(28907072) SHA1(21c7017af8a8ceb8e43d7e798f48518b136fd45c) ) /* Labeled B06-14 and under printed label "Taito M-001, 128P, 720100", is a mask 8042 */
 
 	ROM_REGION( 0x80000, "gfx1", 0 )
 	ROM_LOAD( "b06-01.13a", 0x00000, 0x20000, CRC(d2afbf7e) SHA1(28b4cf94798f049a9f8375464741dbef208d7290) )
@@ -2038,18 +1911,32 @@ ROM_START( extrmatnj )
 	ROM_REGION( 0x0400, "proms", 0 )
 	ROM_LOAD( "b06-09.15f", 0x00000, 0x200, CRC(f388b361) SHA1(f00db6ad6994cfe9b7ad76e30b7049b11f8c16e4) )  /* hi bytes, AM27S29 or compatible like MB7124 */
 	ROM_LOAD( "b06-08.17f", 0x00200, 0x200, CRC(10c9aac3) SHA1(09d6f791dea358e78099af7a370b00b8504ffc97) )  /* lo bytes, AM27S29 or compatible like MB7124 */
+
+	ROM_REGION( 0x10000, "pal", 0 ) /* these are shared with several other games on this hardware */
+	ROM_LOAD( "b06-10.pal16l8a.d9.jed", 0x00000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-11.pal16l8a.d6.jed", 0x01000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-12.pal16l8a.c3.jed", 0x02000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-13.pal16l8a.c2.jed", 0x03000, 0x01000, NO_DUMP)
 ROM_END
 
+/*
+PCB:
+Seta: P0-022-A
+Taito: K1100245A J1100108A
+
+The arknoid2 PCB has a sticker label which says "K1100245A // REVENGE OF DOH"
+*/
+
 ROM_START( arknoid2 )
 	ROM_REGION( 0x20000, "maincpu", 0 )             /* Region 0 - main cpu */
-	ROM_LOAD( "b08_05.11c", 0x00000, 0x10000, CRC(136edf9d) SHA1(f632321650897eee585511a84f451a205d1f7704) )
+	ROM_LOAD( "b08__05.11c", 0x00000, 0x10000, CRC(136edf9d) SHA1(f632321650897eee585511a84f451a205d1f7704) )
 	/* 0x10000 - 0x1ffff empty */
 
 	ROM_REGION( 0x10000, "sub", 0 )             /* Region 2 - sound cpu */
-	ROM_LOAD( "b08_13.3e", 0x00000, 0x10000, CRC(e8035ef1) SHA1(9a54e952cff0036c4b6affd9ffb1097cdccbe255) )
+	ROM_LOAD( "b08__13.3e", 0x00000, 0x10000, CRC(e8035ef1) SHA1(9a54e952cff0036c4b6affd9ffb1097cdccbe255) )
 
-	ROM_REGION( 0x10000, "audiocpu", 0 )    /* M-Chip (i8742 internal ROM) */
-	ROM_LOAD( "ark28742.3g", 0x0000, 0x0800, NO_DUMP )
+	ROM_REGION( 0x10000, "mcu", 0 )    /* M-Chip (i8x42 internal ROM) */
+	ROM_LOAD( "b08__09.3g", 0x0000, 0x0800, NO_DUMP ) /* Labeled B08 // 09 and under printed label "?Taito M-009?", is a mask 8042 */
 
 	ROM_REGION( 0x80000, "gfx1", 0 )
 	ROM_LOAD( "b08-01.13a", 0x00000, 0x20000, CRC(2ccc86b4) SHA1(eced1d7e687db0331507726946b6a19a690a7604) )
@@ -2060,18 +1947,24 @@ ROM_START( arknoid2 )
 	ROM_REGION( 0x0400, "proms", 0 )
 	ROM_LOAD( "b08-08.15f", 0x00000, 0x200, CRC(a4f7ebd9) SHA1(094eb63c18898c6ee8d722492bdfd28091c61773) )  /* hi bytes, AM27S29 or compatible like MB7124 */
 	ROM_LOAD( "b08-07.16f", 0x00200, 0x200, CRC(ea34d9f7) SHA1(9a46edc64f961bd96908419cabd92445d300fc19) )  /* lo bytes, AM27S29 or compatible like MB7124 */
+
+	ROM_REGION( 0x10000, "pal", 0 ) /* these are shared with extermination */
+	ROM_LOAD( "b06-10.pal16l8a.d9.jed", 0x00000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-11.pal16l8a.d6.jed", 0x01000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-12.pal16l8a.c3.jed", 0x02000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-13.pal16l8a.c2.jed", 0x03000, 0x01000, NO_DUMP)
 ROM_END
 
 ROM_START( arknoid2u )
 	ROM_REGION( 0x20000, "maincpu", 0 )             /* Region 0 - main cpu */
-	ROM_LOAD( "b08_11.11c", 0x00000, 0x10000, CRC(99555231) SHA1(2798f3f5b3f1fa27598fe7a6e95c75d9142c8d34) )
+	ROM_LOAD( "b08__11.11c", 0x00000, 0x10000, CRC(99555231) SHA1(2798f3f5b3f1fa27598fe7a6e95c75d9142c8d34) )
 	/* 0x10000 - 0x1ffff empty */
 
 	ROM_REGION( 0x10000, "sub", 0 )             /* Region 2 - sound cpu */
-	ROM_LOAD( "b08_12.3e", 0x00000, 0x10000, CRC(dc84e27d) SHA1(d549d8c9fbec0521517f0c5f5cee763e27d48633) )
+	ROM_LOAD( "b08__12.3e", 0x00000, 0x10000, CRC(dc84e27d) SHA1(d549d8c9fbec0521517f0c5f5cee763e27d48633) )
 
-	ROM_REGION( 0x10000, "audiocpu", 0 )    /* M-Chip (i8742 internal ROM) */
-	ROM_LOAD( "ark28742.3g", 0x0000, 0x0800, NO_DUMP )
+	ROM_REGION( 0x10000, "mcu", 0 )    /* M-Chip (i8x42 internal ROM) */
+	ROM_LOAD( "b08__09.3g", 0x0000, 0x0800, NO_DUMP ) /* Labeled B08 // 09 and under printed label "?Taito M-009?", is a mask 8042 */
 
 	ROM_REGION( 0x80000, "gfx1", 0 )
 	ROM_LOAD( "b08-01.13a", 0x00000, 0x20000, CRC(2ccc86b4) SHA1(eced1d7e687db0331507726946b6a19a690a7604) )
@@ -2082,6 +1975,12 @@ ROM_START( arknoid2u )
 	ROM_REGION( 0x0400, "proms", 0 )
 	ROM_LOAD( "b08-08.15f", 0x00000, 0x200, CRC(a4f7ebd9) SHA1(094eb63c18898c6ee8d722492bdfd28091c61773) )  /* hi bytes, AM27S29 or compatible like MB7124 */
 	ROM_LOAD( "b08-07.16f", 0x00200, 0x200, CRC(ea34d9f7) SHA1(9a46edc64f961bd96908419cabd92445d300fc19) )  /* lo bytes, AM27S29 or compatible like MB7124 */
+
+	ROM_REGION( 0x10000, "pal", 0 ) /* these are shared with extermination */
+	ROM_LOAD( "b06-10.pal16l8a.d9.jed", 0x00000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-11.pal16l8a.d6.jed", 0x01000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-12.pal16l8a.c3.jed", 0x02000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-13.pal16l8a.c2.jed", 0x03000, 0x01000, NO_DUMP)
 ROM_END
 
 ROM_START( arknoid2j )
@@ -2092,8 +1991,8 @@ ROM_START( arknoid2j )
 	ROM_REGION( 0x10000, "sub", 0 )             /* Region 2 - sound cpu */
 	ROM_LOAD( "b08_06.3e", 0x00000, 0x10000, CRC(adfcd40c) SHA1(f91299407ed21e2dd244c9b1a315b27ed32f5514) )
 
-	ROM_REGION( 0x10000, "audiocpu", 0 )    /* M-Chip (i8742 internal ROM) */
-	ROM_LOAD( "ark28742.3g", 0x0000, 0x0800, NO_DUMP )
+	ROM_REGION( 0x10000, "mcu", 0 )    /* M-Chip (i8x42 internal ROM) */
+	ROM_LOAD( "b08__09.3g", 0x0000, 0x0800, NO_DUMP ) /* Labeled B08 // 09 and under printed label "?Taito M-009?", is a mask 8042 */
 
 	ROM_REGION( 0x80000, "gfx1", 0 )
 	ROM_LOAD( "b08-01.13a", 0x00000, 0x20000, CRC(2ccc86b4) SHA1(eced1d7e687db0331507726946b6a19a690a7604) )
@@ -2104,6 +2003,12 @@ ROM_START( arknoid2j )
 	ROM_REGION( 0x0400, "proms", 0 )
 	ROM_LOAD( "b08-08.15f", 0x00000, 0x200, CRC(a4f7ebd9) SHA1(094eb63c18898c6ee8d722492bdfd28091c61773) )  /* hi bytes, AM27S29 or compatible like MB7124 */
 	ROM_LOAD( "b08-07.16f", 0x00200, 0x200, CRC(ea34d9f7) SHA1(9a46edc64f961bd96908419cabd92445d300fc19) )  /* lo bytes, AM27S29 or compatible like MB7124 */
+
+	ROM_REGION( 0x10000, "pal", 0 ) /* these are shared with extermination */
+	ROM_LOAD( "b06-10.pal16l8a.d9.jed", 0x00000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-11.pal16l8a.d6.jed", 0x01000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-12.pal16l8a.c3.jed", 0x02000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-13.pal16l8a.c2.jed", 0x03000, 0x01000, NO_DUMP)
 ROM_END
 
 ROM_START( arknoid2b )
@@ -2114,8 +2019,8 @@ ROM_START( arknoid2b )
 	ROM_REGION( 0x10000, "sub", 0 )             /* Region 2 - sound cpu */
 	ROM_LOAD( "b08_13.3e", 0x00000, 0x10000, CRC(e8035ef1) SHA1(9a54e952cff0036c4b6affd9ffb1097cdccbe255) )
 
-	ROM_REGION( 0x10000, "audiocpu", 0 )    /* M-Chip (i8742 internal ROM) */
-	ROM_LOAD( "ark28742.3g", 0x0000, 0x0800, NO_DUMP )
+	ROM_REGION( 0x10000, "mcu", 0 )    /* M-Chip (i8x42 internal ROM) */
+	ROM_LOAD( "ark28742.3g", 0x0000, 0x0800, NO_DUMP ) /* Labeled B08 // 09 and under printed label "?Taito M-009?", is a mask 8042... does the bootleg set even HAVE the mcu? */
 
 	ROM_REGION( 0x80000, "gfx1", 0 )
 	ROM_LOAD( "b08-01.13a", 0x00000, 0x20000, CRC(2ccc86b4) SHA1(eced1d7e687db0331507726946b6a19a690a7604) )
@@ -2126,88 +2031,119 @@ ROM_START( arknoid2b )
 	ROM_REGION( 0x0400, "proms", 0 )
 	ROM_LOAD( "b08-08.15f", 0x00000, 0x200, CRC(a4f7ebd9) SHA1(094eb63c18898c6ee8d722492bdfd28091c61773) )  /* hi bytes, AM27S29 or compatible like MB7124 */
 	ROM_LOAD( "b08-07.16f", 0x00200, 0x200, CRC(ea34d9f7) SHA1(9a46edc64f961bd96908419cabd92445d300fc19) )  /* lo bytes, AM27S29 or compatible like MB7124 */
+
+	ROM_REGION( 0x10000, "pal", 0 ) /* these are shared with extermination */
+	ROM_LOAD( "b06-10.pal16l8a.d9.jed", 0x00000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-11.pal16l8a.d6.jed", 0x01000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-12.pal16l8a.c3.jed", 0x02000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-13.pal16l8a.c2.jed", 0x03000, 0x01000, NO_DUMP)
 ROM_END
 
+/*
+PCB:
+Seta: P0-025-A
+Taito: K1100241A J1100107A
+
+The drtoppelj PCB has a sticker label which says "K1100269A // DR. ドツペル タンケン" (DoTuPeRu TaNKeN)
+*/
 ROM_START( drtoppel )
 	ROM_REGION( 0x20000, "maincpu", 0 ) /* 64k + bankswitch areas for the first CPU */
-	ROM_LOAD( "b19-09.11c", 0x00000, 0x10000, CRC(3e654f82) SHA1(d9e351d82546b08eb7887ea1d976fa97a259db6e) )
-	ROM_LOAD( "b19-10.9c",  0x10000, 0x10000, CRC(7e72fd25) SHA1(6035e4db75e6dc57b13bb6e92217d1c2d0ffdfd2) )
+	ROM_LOAD( "b19__09.11c", 0x00000, 0x10000, CRC(3e654f82) SHA1(d9e351d82546b08eb7887ea1d976fa97a259db6e) )
+	ROM_LOAD( "b19__10.9c",  0x10000, 0x10000, CRC(7e72fd25) SHA1(6035e4db75e6dc57b13bb6e92217d1c2d0ffdfd2) )
 
 	ROM_REGION( 0x10000, "sub", 0 ) /* 64k for the second CPU */
-	ROM_LOAD( "b19-15.3e", 0x00000, 0x10000, CRC(37a0d3fb) SHA1(f65fb9382af5f5b09725c39b660c5138b3912f53) ) /* Hacked??, need correct Taito rom number */
+	ROM_LOAD( "b19__15.3e", 0x00000, 0x10000, BAD_DUMP CRC(37a0d3fb) SHA1(f65fb9382af5f5b09725c39b660c5138b3912f53) ) /* Region-Hacked??, need correct Taito rom number */
 
-	ROM_REGION( 0x10000, "audiocpu", 0 )    /* M-Chip (i8742 internal ROM) */
-	ROM_LOAD( "drt8742.3g", 0x0000, 0x0800, NO_DUMP ) /* Labeled B06-14, reused from Extermination, under printed label "Taito M-001, 128P, 720100" */
+	ROM_REGION( 0x10000, "mcu", 0 )    /* M-Chip (i8x42 internal ROM) */
+	ROM_LOAD( "b06__14.1g", 0x0000, 0x0800, CRC(28907072) SHA1(21c7017af8a8ceb8e43d7e798f48518b136fd45c) ) /* Labeled B06 // 14 and under printed label "Taito M-001, 128P, 720100", is a mask 8042 */
 
 	ROM_REGION( 0x100000, "gfx1", 0 )
-	ROM_LOAD( "b19-01.13a", 0x00000, 0x20000, CRC(a7e8a0c1) SHA1(a2f017ae5b6472d4202f126d0247b3fe4b1321d1) )
-	ROM_LOAD( "b19-02.12a", 0x20000, 0x20000, CRC(790ae654) SHA1(5fd6b89918e1539e00c918959b96d2a9394c8abe) )
-	ROM_LOAD( "b19-03.10a", 0x40000, 0x20000, CRC(495c4c5a) SHA1(a23b512cda4c0c535df5508a52faebe401c1797d) )
-	ROM_LOAD( "b19-04.8a",  0x60000, 0x20000, CRC(647007a0) SHA1(10ec35a15091967038bb26fb116c47d730f69edc) )
-	ROM_LOAD( "b19-05.7a",  0x80000, 0x20000, CRC(49f2b1a5) SHA1(5e98bb421afaa02471ad02213ea6ca23ff2f0e27) )
-	ROM_LOAD( "b19-06.5a",  0xa0000, 0x20000, CRC(2d39f1d0) SHA1(2aa89a5cc7f026c8db9922b183319ff66ac4a071) )
-	ROM_LOAD( "b19-07.4a",  0xc0000, 0x20000, CRC(8bb06f41) SHA1(a0c182d473317f2cdb31bdf39a2593c032002305) )
-	ROM_LOAD( "b19-08.2a",  0xe0000, 0x20000, CRC(3584b491) SHA1(d0aca90708be241bbd3a1097220a85083337a4bc) )
+	ROM_LOAD( "b19-01.23c1000.13a", 0x00000, 0x20000, CRC(a7e8a0c1) SHA1(a2f017ae5b6472d4202f126d0247b3fe4b1321d1) )
+	ROM_LOAD( "b19-02.23c1000.12a", 0x20000, 0x20000, CRC(790ae654) SHA1(5fd6b89918e1539e00c918959b96d2a9394c8abe) )
+	ROM_LOAD( "b19-03.23c1000.10a", 0x40000, 0x20000, CRC(495c4c5a) SHA1(a23b512cda4c0c535df5508a52faebe401c1797d) )
+	ROM_LOAD( "b19-04.23c1000.8a",  0x60000, 0x20000, CRC(647007a0) SHA1(10ec35a15091967038bb26fb116c47d730f69edc) )
+	ROM_LOAD( "b19-05.23c1000.7a",  0x80000, 0x20000, CRC(49f2b1a5) SHA1(5e98bb421afaa02471ad02213ea6ca23ff2f0e27) )
+	ROM_LOAD( "b19-06.23c1000.5a",  0xa0000, 0x20000, CRC(2d39f1d0) SHA1(2aa89a5cc7f026c8db9922b183319ff66ac4a071) )
+	ROM_LOAD( "b19-07.23c1000.4a",  0xc0000, 0x20000, CRC(8bb06f41) SHA1(a0c182d473317f2cdb31bdf39a2593c032002305) )
+	ROM_LOAD( "b19-08.23c1000.2a",  0xe0000, 0x20000, CRC(3584b491) SHA1(d0aca90708be241bbd3a1097220a85083337a4bc) )
 
 	ROM_REGION( 0x0400, "proms", 0 )        /* color proms */
-	ROM_LOAD( "b19-13.15f", 0x0000, 0x200, CRC(6a547980) SHA1(c82f8dfad028565b4b4e5be1167f2f290c929090) )   /* hi bytes, AM27S29 or compatible like MB7124 */
-	ROM_LOAD( "b19-12.16f", 0x0200, 0x200, CRC(5754e9d8) SHA1(8c7d29e22c90b1f72929b95675dc15e431aae044) )   /* lo bytes, AM27S29 or compatible like MB7124 */
+	ROM_LOAD( "b19-13.am27s29.15f", 0x0000, 0x200, CRC(6a547980) SHA1(c82f8dfad028565b4b4e5be1167f2f290c929090) )   /* hi bytes, AM27S29 or compatible like MB7124 */
+	ROM_LOAD( "b19-12.am27s29.16f", 0x0200, 0x200, CRC(5754e9d8) SHA1(8c7d29e22c90b1f72929b95675dc15e431aae044) )   /* lo bytes, AM27S29 or compatible like MB7124 */
+
+	ROM_REGION( 0x10000, "pal", 0 ) /* these are shared with extermination */
+	ROM_LOAD( "b06-10.pal16l8a.d9.jed", 0x00000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-11.pal16l8a.d6.jed", 0x01000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-12.pal16l8a.c3.jed", 0x02000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-13.pal16l8a.c2.jed", 0x03000, 0x01000, NO_DUMP)
 ROM_END
 
 ROM_START( drtoppelu )
 	ROM_REGION( 0x20000, "maincpu", 0 ) /* 64k + bankswitch areas for the first CPU */
-	ROM_LOAD( "b19-09.11c", 0x00000, 0x10000, CRC(3e654f82) SHA1(d9e351d82546b08eb7887ea1d976fa97a259db6e) )
-	ROM_LOAD( "b19-10.9c",  0x10000, 0x10000, CRC(7e72fd25) SHA1(6035e4db75e6dc57b13bb6e92217d1c2d0ffdfd2) )
+	ROM_LOAD( "b19__09.11c", 0x00000, 0x10000, CRC(3e654f82) SHA1(d9e351d82546b08eb7887ea1d976fa97a259db6e) )
+	ROM_LOAD( "b19__10.9c",  0x10000, 0x10000, CRC(7e72fd25) SHA1(6035e4db75e6dc57b13bb6e92217d1c2d0ffdfd2) )
 
 	ROM_REGION( 0x10000, "sub", 0 ) /* 64k for the second CPU */
-	ROM_LOAD( "b19-14.3e", 0x00000, 0x10000, CRC(05565b22) SHA1(d1aa47b438d3b44c5177337809e38b50f6445c36) ) /* Hacked??, need correct Taito rom number */
+	ROM_LOAD( "b19__14.3e", 0x00000, 0x10000, BAD_DUMP CRC(05565b22) SHA1(d1aa47b438d3b44c5177337809e38b50f6445c36) ) /* Region-Hacked??, need correct Taito rom number */
 
-	ROM_REGION( 0x10000, "audiocpu", 0 )    /* M-Chip (i8742 internal ROM) */
-	ROM_LOAD( "drt8742.3g", 0x0000, 0x0800, NO_DUMP ) /* Labeled B06-14, reused from Extermination, under printed label "Taito M-001, 128P, 720100" */
+	ROM_REGION( 0x10000, "mcu", 0 )    /* M-Chip (i8x42 internal ROM) */
+	ROM_LOAD( "b06__14.1g", 0x0000, 0x0800, CRC(28907072) SHA1(21c7017af8a8ceb8e43d7e798f48518b136fd45c) ) /* Labeled B06 // 14 and under printed label "Taito M-001, 128P, 720100", is a mask 8042 */
 
 	ROM_REGION( 0x100000, "gfx1", 0 )
-	ROM_LOAD( "b19-01.13a", 0x00000, 0x20000, CRC(a7e8a0c1) SHA1(a2f017ae5b6472d4202f126d0247b3fe4b1321d1) )
-	ROM_LOAD( "b19-02.12a", 0x20000, 0x20000, CRC(790ae654) SHA1(5fd6b89918e1539e00c918959b96d2a9394c8abe) )
-	ROM_LOAD( "b19-03.10a", 0x40000, 0x20000, CRC(495c4c5a) SHA1(a23b512cda4c0c535df5508a52faebe401c1797d) )
-	ROM_LOAD( "b19-04.8a",  0x60000, 0x20000, CRC(647007a0) SHA1(10ec35a15091967038bb26fb116c47d730f69edc) )
-	ROM_LOAD( "b19-05.7a",  0x80000, 0x20000, CRC(49f2b1a5) SHA1(5e98bb421afaa02471ad02213ea6ca23ff2f0e27) )
-	ROM_LOAD( "b19-06.5a",  0xa0000, 0x20000, CRC(2d39f1d0) SHA1(2aa89a5cc7f026c8db9922b183319ff66ac4a071) )
-	ROM_LOAD( "b19-07.4a",  0xc0000, 0x20000, CRC(8bb06f41) SHA1(a0c182d473317f2cdb31bdf39a2593c032002305) )
-	ROM_LOAD( "b19-08.2a",  0xe0000, 0x20000, CRC(3584b491) SHA1(d0aca90708be241bbd3a1097220a85083337a4bc) )
+	ROM_LOAD( "b19-01.23c1000.13a", 0x00000, 0x20000, CRC(a7e8a0c1) SHA1(a2f017ae5b6472d4202f126d0247b3fe4b1321d1) )
+	ROM_LOAD( "b19-02.23c1000.12a", 0x20000, 0x20000, CRC(790ae654) SHA1(5fd6b89918e1539e00c918959b96d2a9394c8abe) )
+	ROM_LOAD( "b19-03.23c1000.10a", 0x40000, 0x20000, CRC(495c4c5a) SHA1(a23b512cda4c0c535df5508a52faebe401c1797d) )
+	ROM_LOAD( "b19-04.23c1000.8a",  0x60000, 0x20000, CRC(647007a0) SHA1(10ec35a15091967038bb26fb116c47d730f69edc) )
+	ROM_LOAD( "b19-05.23c1000.7a",  0x80000, 0x20000, CRC(49f2b1a5) SHA1(5e98bb421afaa02471ad02213ea6ca23ff2f0e27) )
+	ROM_LOAD( "b19-06.23c1000.5a",  0xa0000, 0x20000, CRC(2d39f1d0) SHA1(2aa89a5cc7f026c8db9922b183319ff66ac4a071) )
+	ROM_LOAD( "b19-07.23c1000.4a",  0xc0000, 0x20000, CRC(8bb06f41) SHA1(a0c182d473317f2cdb31bdf39a2593c032002305) )
+	ROM_LOAD( "b19-08.23c1000.2a",  0xe0000, 0x20000, CRC(3584b491) SHA1(d0aca90708be241bbd3a1097220a85083337a4bc) )
 
 	ROM_REGION( 0x0400, "proms", 0 )        /* color proms */
-	ROM_LOAD( "b19-13.15f", 0x0000, 0x200, CRC(6a547980) SHA1(c82f8dfad028565b4b4e5be1167f2f290c929090) )   /* hi bytes, AM27S29 or compatible like MB7124 */
-	ROM_LOAD( "b19-12.16f", 0x0200, 0x200, CRC(5754e9d8) SHA1(8c7d29e22c90b1f72929b95675dc15e431aae044) )   /* lo bytes, AM27S29 or compatible like MB7124 */
+	ROM_LOAD( "b19-13.am27s29.15f", 0x0000, 0x200, CRC(6a547980) SHA1(c82f8dfad028565b4b4e5be1167f2f290c929090) )   /* hi bytes, AM27S29 or compatible like MB7124 */
+	ROM_LOAD( "b19-12.am27s29.16f", 0x0200, 0x200, CRC(5754e9d8) SHA1(8c7d29e22c90b1f72929b95675dc15e431aae044) )   /* lo bytes, AM27S29 or compatible like MB7124 */
+
+	ROM_REGION( 0x10000, "pal", 0 ) /* these are shared with extermination */
+	ROM_LOAD( "b06-10.pal16l8a.d9.jed", 0x00000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-11.pal16l8a.d6.jed", 0x01000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-12.pal16l8a.c3.jed", 0x02000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-13.pal16l8a.c2.jed", 0x03000, 0x01000, NO_DUMP)
 ROM_END
 
 ROM_START( drtoppelj )
 	ROM_REGION( 0x20000, "maincpu", 0 ) /* 64k + bankswitch areas for the first CPU */
-	ROM_LOAD( "b19-09.11c", 0x00000, 0x10000, CRC(3e654f82) SHA1(d9e351d82546b08eb7887ea1d976fa97a259db6e) )
-	ROM_LOAD( "b19-10.9c",  0x10000, 0x10000, CRC(7e72fd25) SHA1(6035e4db75e6dc57b13bb6e92217d1c2d0ffdfd2) )
+	ROM_LOAD( "b19__09.11c", 0x00000, 0x10000, CRC(3e654f82) SHA1(d9e351d82546b08eb7887ea1d976fa97a259db6e) )
+	ROM_LOAD( "b19__10.9c",  0x10000, 0x10000, CRC(7e72fd25) SHA1(6035e4db75e6dc57b13bb6e92217d1c2d0ffdfd2) )
 
 	ROM_REGION( 0x10000, "sub", 0 ) /* 64k for the second CPU */
-	ROM_LOAD( "b19-11.3e", 0x00000, 0x10000, CRC(524dc249) SHA1(158b2de0fcd17ad16ba72bb24888122bf704e216) )
+	ROM_LOAD( "b19__11.3e", 0x00000, 0x10000, CRC(524dc249) SHA1(158b2de0fcd17ad16ba72bb24888122bf704e216) )
 
-	ROM_REGION( 0x10000, "audiocpu", 0 )    /* M-Chip (i8742 internal ROM) */
-	ROM_LOAD( "drt8742.3g", 0x0000, 0x0800, NO_DUMP ) /* Labeled B06-14, reused from Extermination, under printed label "Taito M-001, 128P, 720100" */
+	ROM_REGION( 0x10000, "mcu", 0 )    /* M-Chip (i8x42 internal ROM) */
+	ROM_LOAD( "b06__14.1g", 0x0000, 0x0800, CRC(28907072) SHA1(21c7017af8a8ceb8e43d7e798f48518b136fd45c) ) /* Labeled B06 // 14 and under printed label "Taito M-001, 128P, 720100", is a mask 8042 */
 
 	ROM_REGION( 0x100000, "gfx1", 0 )
-	ROM_LOAD( "b19-01.13a", 0x00000, 0x20000, CRC(a7e8a0c1) SHA1(a2f017ae5b6472d4202f126d0247b3fe4b1321d1) )
-	ROM_LOAD( "b19-02.12a", 0x20000, 0x20000, CRC(790ae654) SHA1(5fd6b89918e1539e00c918959b96d2a9394c8abe) )
-	ROM_LOAD( "b19-03.10a", 0x40000, 0x20000, CRC(495c4c5a) SHA1(a23b512cda4c0c535df5508a52faebe401c1797d) )
-	ROM_LOAD( "b19-04.8a",  0x60000, 0x20000, CRC(647007a0) SHA1(10ec35a15091967038bb26fb116c47d730f69edc) )
-	ROM_LOAD( "b19-05.7a",  0x80000, 0x20000, CRC(49f2b1a5) SHA1(5e98bb421afaa02471ad02213ea6ca23ff2f0e27) )
-	ROM_LOAD( "b19-06.5a",  0xa0000, 0x20000, CRC(2d39f1d0) SHA1(2aa89a5cc7f026c8db9922b183319ff66ac4a071) )
-	ROM_LOAD( "b19-07.4a",  0xc0000, 0x20000, CRC(8bb06f41) SHA1(a0c182d473317f2cdb31bdf39a2593c032002305) )
-	ROM_LOAD( "b19-08.2a",  0xe0000, 0x20000, CRC(3584b491) SHA1(d0aca90708be241bbd3a1097220a85083337a4bc) )
+	ROM_LOAD( "b19-01.23c1000.13a", 0x00000, 0x20000, CRC(a7e8a0c1) SHA1(a2f017ae5b6472d4202f126d0247b3fe4b1321d1) )
+	ROM_LOAD( "b19-02.23c1000.12a", 0x20000, 0x20000, CRC(790ae654) SHA1(5fd6b89918e1539e00c918959b96d2a9394c8abe) )
+	ROM_LOAD( "b19-03.23c1000.10a", 0x40000, 0x20000, CRC(495c4c5a) SHA1(a23b512cda4c0c535df5508a52faebe401c1797d) )
+	ROM_LOAD( "b19-04.23c1000.8a",  0x60000, 0x20000, CRC(647007a0) SHA1(10ec35a15091967038bb26fb116c47d730f69edc) )
+	ROM_LOAD( "b19-05.23c1000.7a",  0x80000, 0x20000, CRC(49f2b1a5) SHA1(5e98bb421afaa02471ad02213ea6ca23ff2f0e27) )
+	ROM_LOAD( "b19-06.23c1000.5a",  0xa0000, 0x20000, CRC(2d39f1d0) SHA1(2aa89a5cc7f026c8db9922b183319ff66ac4a071) )
+	ROM_LOAD( "b19-07.23c1000.4a",  0xc0000, 0x20000, CRC(8bb06f41) SHA1(a0c182d473317f2cdb31bdf39a2593c032002305) )
+	ROM_LOAD( "b19-08.23c1000.2a",  0xe0000, 0x20000, CRC(3584b491) SHA1(d0aca90708be241bbd3a1097220a85083337a4bc) )
 
 	ROM_REGION( 0x0400, "proms", 0 )        /* color proms */
-	ROM_LOAD( "b19-13.15f", 0x0000, 0x200, CRC(6a547980) SHA1(c82f8dfad028565b4b4e5be1167f2f290c929090) )   /* hi bytes, AM27S29 or compatible like MB7124 */
-	ROM_LOAD( "b19-12.16f", 0x0200, 0x200, CRC(5754e9d8) SHA1(8c7d29e22c90b1f72929b95675dc15e431aae044) )   /* lo bytes, AM27S29 or compatible like MB7124 */
+	ROM_LOAD( "b19-13.am27s29.15f", 0x0000, 0x200, CRC(6a547980) SHA1(c82f8dfad028565b4b4e5be1167f2f290c929090) )   /* hi bytes, AM27S29 or compatible like MB7124 */
+	ROM_LOAD( "b19-12.am27s29.16f", 0x0200, 0x200, CRC(5754e9d8) SHA1(8c7d29e22c90b1f72929b95675dc15e431aae044) )   /* lo bytes, AM27S29 or compatible like MB7124 */
+
+	ROM_REGION( 0x10000, "pal", 0 ) /* these are shared with extermination */
+	ROM_LOAD( "b06-10.pal16l8a.d9.jed", 0x00000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-11.pal16l8a.d6.jed", 0x01000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-12.pal16l8a.c3.jed", 0x02000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-13.pal16l8a.c2.jed", 0x03000, 0x01000, NO_DUMP)
 ROM_END
 
 /* M6100309A PCB
-   P0-0038A */
+   P0-038A */
 ROM_START( kageki )
 	ROM_REGION( 0x20000, "maincpu", 0 )
 	ROM_LOAD( "b35-16.11c", 0x00000, 0x10000, CRC(a4e6fd58) SHA1(7cfe5b3fa6c88cdab45719f5b58541270825ad30) )    /* US ver */
@@ -2217,17 +2153,23 @@ ROM_START( kageki )
 	ROM_LOAD( "b35-17.43e", 0x00000, 0x10000, CRC(fdd9c246) SHA1(ac7a59ed19d0d81748cabd8b77a6ba3937e3cc99) )    /* US ver */
 
 	ROM_REGION( 0x100000, "gfx1", 0 )
-	ROM_LOAD( "b35-01.13a",  0x00000, 0x20000, CRC(01d83a69) SHA1(92a84329306b58a45f7bb443a8642eeaeb04d553) )
-	ROM_LOAD( "b35-02.12a",  0x20000, 0x20000, CRC(d8af47ac) SHA1(2ef9ca991bf55ed6c12bf3a7dc4aa904d7749d5c) )
-	ROM_LOAD( "b35-03.10a",  0x40000, 0x20000, CRC(3cb68797) SHA1(e7669b1a9a26dede560cc87695004d29510bc1f5) )
-	ROM_LOAD( "b35-04.8a",   0x60000, 0x20000, CRC(71c03f91) SHA1(edce6e5a52b0c83c1c3c6bf9bc6b7957f7941521) )
-	ROM_LOAD( "b35-05.7a",   0x80000, 0x20000, CRC(a4e20c08) SHA1(5d1d23d1410fea8650b18c595b0170a17e5d89a6) )
-	ROM_LOAD( "b35-06.5a",   0xa0000, 0x20000, CRC(3f8ab658) SHA1(44de7ee2bdb89bc520ed9bc812c26789c3f31411) )
-	ROM_LOAD( "b35-07.4a",   0xc0000, 0x20000, CRC(1b4af049) SHA1(09783816d5076219d241538e2711402eb8c4cd03) )
-	ROM_LOAD( "b35-08.2a",   0xe0000, 0x20000, CRC(deb2268c) SHA1(318bf3da6cbe20758397d5f78caf3cda02f322d7) )
+	ROM_LOAD( "b35__01.13a",  0x00000, 0x20000, CRC(01d83a69) SHA1(92a84329306b58a45f7bb443a8642eeaeb04d553) )
+	ROM_LOAD( "b35__02.12a",  0x20000, 0x20000, CRC(d8af47ac) SHA1(2ef9ca991bf55ed6c12bf3a7dc4aa904d7749d5c) )
+	ROM_LOAD( "b35__03.10a",  0x40000, 0x20000, CRC(3cb68797) SHA1(e7669b1a9a26dede560cc87695004d29510bc1f5) )
+	ROM_LOAD( "b35__04.8a",   0x60000, 0x20000, CRC(71c03f91) SHA1(edce6e5a52b0c83c1c3c6bf9bc6b7957f7941521) )
+	ROM_LOAD( "b35__05.7a",   0x80000, 0x20000, CRC(a4e20c08) SHA1(5d1d23d1410fea8650b18c595b0170a17e5d89a6) )
+	ROM_LOAD( "b35__06.5a",   0xa0000, 0x20000, CRC(3f8ab658) SHA1(44de7ee2bdb89bc520ed9bc812c26789c3f31411) )
+	ROM_LOAD( "b35__07.4a",   0xc0000, 0x20000, CRC(1b4af049) SHA1(09783816d5076219d241538e2711402eb8c4cd03) )
+	ROM_LOAD( "b35__08.2a",   0xe0000, 0x20000, CRC(deb2268c) SHA1(318bf3da6cbe20758397d5f78caf3cda02f322d7) )
 
 	ROM_REGION( 0x10000, "samples", 0 ) /* samples */
 	ROM_LOAD( "b35-15.98g",  0x00000, 0x10000, CRC(e6212a0f) SHA1(43891f4fd141b00ed458be47a107a2550a0534c2) )   /* US ver */
+
+	ROM_REGION( 0x10000, "pal", 0 ) /* these are shared with extermination except d9 */
+	ROM_LOAD( "b06-101.pal16l8a.d9.jed", 0x00000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-11.pal16l8a.d6.jed", 0x01000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-12.pal16l8a.c3.jed", 0x02000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-13.pal16l8a.c2.jed", 0x03000, 0x01000, NO_DUMP)
 ROM_END
 
 ROM_START( kagekij )
@@ -2250,6 +2192,12 @@ ROM_START( kagekij )
 
 	ROM_REGION( 0x10000, "samples", 0 ) /* samples */
 	ROM_LOAD( "b35-12.98g", 0x00000, 0x10000, CRC(184409f1) SHA1(711bdd499670e86630ebb6820262b1d8d651c987) )    /* JP ver */
+
+	ROM_REGION( 0x10000, "pal", 0 ) /* these are shared with extermination except d9 */
+	ROM_LOAD( "b06-101.pal16l8a.d9.jed", 0x00000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-11.pal16l8a.d6.jed", 0x01000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-12.pal16l8a.c3.jed", 0x02000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-13.pal16l8a.c2.jed", 0x03000, 0x01000, NO_DUMP)
 ROM_END
 
 /* Board ID is M6100309A - program rom has been hacked to say 1992 :/
@@ -2276,6 +2224,12 @@ ROM_START( kagekih )
 
 	ROM_REGION( 0x10000, "samples", 0 ) /* samples */
 	ROM_LOAD( "b35-12.98g", 0x00000, 0x10000, CRC(184409f1) SHA1(711bdd499670e86630ebb6820262b1d8d651c987) )    /* JP ver */
+
+	ROM_REGION( 0x10000, "pal", 0 ) /* these are shared with extermination except d9 */
+	ROM_LOAD( "b06-101.pal16l8a.d9.jed", 0x00000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-11.pal16l8a.d6.jed", 0x01000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-12.pal16l8a.c3.jed", 0x02000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-13.pal16l8a.c2.jed", 0x03000, 0x01000, NO_DUMP)
 ROM_END
 
 
@@ -2283,7 +2237,22 @@ ROM_END
 Chuka Taisen
 Taito, 1988
 
-PCB Layout
+This PCB comes in two variations: one which is on the older, color prom based P0-025-A PCB as used on extrmatn, drtoppel
+and one which is a unique PCB sort of an 'older version of p0-051-a' which uses color ram like tnzs.
+The color prom version is not dumped yet.
+
+The chukatai (p0-025-a) PCB has a sticker label which says "????????? // CHUKATAISEN"
+The chukatai (p0-028-a) PCB has a sticker label which says "K1100??2A // CHUKATAISEN"
+
+PCB:
+Older(technically 'newer rom ids but used to get rid of old pcb stock') set is:
+Seta: P0-025-A
+Taito: K1100241A J1100107A
+
+The two newer sets are:
+Seta: P0-028-A
+Taito: K1100416A J1100332A
+which is described in the diagram below.
 
 |--------------------------------------------------|
 |    SETA                     SETA         12MHz   |
@@ -2316,6 +2285,13 @@ PCB Layout
 Notes:
       6264: 8K x8 SRAM
       6116: 2K x8 SRAM
+
+The undumped Chuka Taisen set has a daughterboard which plugs into the
+GFX ROM sockets and allows use of 27c1000d eproms instead of 23c1000 mask roms.
+The undumped set, unlike the two here, runs on an older drtoppel/extrmatn pcb
+and uses color proms!
+
+
 */
 
 ROM_START( chukatai )
@@ -2326,8 +2302,8 @@ ROM_START( chukatai )
 	ROM_REGION( 0x10000, "sub", 0 ) /* 64k for the second CPU */
 	ROM_LOAD( "b44-12w", 0x00000, 0x10000, CRC(e80ecdca) SHA1(cd96403ca97f18f630118dcb3dc2179c01147213) ) /* Hacked??, need correct Taito rom number */
 
-	ROM_REGION( 0x10000, "mcu", 0 ) /* M-Chip (i8742 internal ROM) */
-	ROM_LOAD( "b44-8742.mcu", 0x0000, 0x0800, CRC(7dff3f9f) SHA1(bbf4e036d025fe8179b053d639f9b8ad401e6e68) )
+	ROM_REGION( 0x10000, "mcu", 0 ) /* M-Chip (i8x42 internal ROM) */
+	ROM_LOAD( "b44-8742.mcu", 0x0000, 0x0800, CRC(7dff3f9f) SHA1(bbf4e036d025fe8179b053d639f9b8ad401e6e68) ) /* B44 // 09 is the label? what is the mask number under the label? maybe Taito M-011? last digit is definitely 1 */
 
 	ROM_REGION( 0x100000, "gfx1", 0 )
 	ROM_LOAD( "b44-01.a13", 0x00000, 0x20000, CRC(aae7b3d5) SHA1(52809ea22d98811ece2fb27e80db6ddf4fbacb07) )
@@ -2338,6 +2314,12 @@ ROM_START( chukatai )
 	ROM_LOAD( "b44-06.a05", 0xa0000, 0x20000, CRC(269978a8) SHA1(aef7b8d3d00dcc4201e0a1e28026f6f1bdafd0b7) )
 	ROM_LOAD( "b44-07.a04", 0xc0000, 0x20000, CRC(3e0e737e) SHA1(f8d62c7b69c79da9df7ef5ce454060d3645e5884) )
 	ROM_LOAD( "b44-08.a02", 0xe0000, 0x20000, CRC(6cb1e8fc) SHA1(4ab0c2cce1de2616044a9bfb9bf17f95a49baffd) )
+
+	ROM_REGION( 0x10000, "pal", 0 ) /* these are shared with extermination except d9 */
+	ROM_LOAD( "b06-101.pal16l8a.d9.jed", 0x00000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-11.pal16l8a.d6.jed", 0x01000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-12.pal16l8a.c3.jed", 0x02000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-13.pal16l8a.c2.jed", 0x03000, 0x01000, NO_DUMP)
 ROM_END
 
 ROM_START( chukataiu )
@@ -2346,10 +2328,10 @@ ROM_START( chukataiu )
 	ROM_LOAD( "b44-11", 0x10000, 0x10000, CRC(32484094) SHA1(f320fea2910816b5085ca9aa37e30af665fb6be1) )
 
 	ROM_REGION( 0x10000, "sub", 0 ) /* 64k for the second CPU */
-	ROM_LOAD( "b44-12u", 0x00000, 0x10000, CRC(9f09fd5c) SHA1(ae92f2e893e1e666dcabbd793f1a778c5e3d7bab) ) /* Hacked??, need correct Taito rom number */
+	ROM_LOAD( "b44-12u", 0x00000, 0x10000, BAD_DUMP CRC(9f09fd5c) SHA1(ae92f2e893e1e666dcabbd793f1a778c5e3d7bab) ) /* Hacked??, need correct Taito rom number */
 
-	ROM_REGION( 0x1000, "mcu", 0 )  /* M-Chip (i8742 internal ROM) */
-	ROM_LOAD( "b44-8742.mcu", 0x0000, 0x0800, CRC(7dff3f9f) SHA1(bbf4e036d025fe8179b053d639f9b8ad401e6e68) )
+	ROM_REGION( 0x1000, "mcu", 0 )  /* M-Chip (i8x42 internal ROM) */
+	ROM_LOAD( "b44-8742.mcu", 0x0000, 0x0800, CRC(7dff3f9f) SHA1(bbf4e036d025fe8179b053d639f9b8ad401e6e68) ) /* B44 // 09 is the label? what is the mask number under the label? maybe Taito M-011? last digit is definitely 1 */
 
 	ROM_REGION( 0x100000, "gfx1", 0 )
 	ROM_LOAD( "b44-01.a13", 0x00000, 0x20000, CRC(aae7b3d5) SHA1(52809ea22d98811ece2fb27e80db6ddf4fbacb07) )
@@ -2360,6 +2342,12 @@ ROM_START( chukataiu )
 	ROM_LOAD( "b44-06.a05", 0xa0000, 0x20000, CRC(269978a8) SHA1(aef7b8d3d00dcc4201e0a1e28026f6f1bdafd0b7) )
 	ROM_LOAD( "b44-07.a04", 0xc0000, 0x20000, CRC(3e0e737e) SHA1(f8d62c7b69c79da9df7ef5ce454060d3645e5884) )
 	ROM_LOAD( "b44-08.a02", 0xe0000, 0x20000, CRC(6cb1e8fc) SHA1(4ab0c2cce1de2616044a9bfb9bf17f95a49baffd) )
+
+	ROM_REGION( 0x10000, "pal", 0 ) /* these are shared with extermination except d9 */
+	ROM_LOAD( "b06-101.pal16l8a.d9.jed", 0x00000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-11.pal16l8a.d6.jed", 0x01000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-12.pal16l8a.c3.jed", 0x02000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-13.pal16l8a.c2.jed", 0x03000, 0x01000, NO_DUMP)
 ROM_END
 
 ROM_START( chukataij )
@@ -2370,8 +2358,8 @@ ROM_START( chukataij )
 	ROM_REGION( 0x10000, "sub", 0 ) /* 64k for the second CPU */
 	ROM_LOAD( "b44-12", 0x00000, 0x10000, CRC(0600ace6) SHA1(3d5767b91ea63128bfbff3527ddcf90fcf43af2e) )
 
-	ROM_REGION( 0x10000, "mcu", 0 ) /* M-Chip (i8742 internal ROM) */
-	ROM_LOAD( "b44-8742.mcu", 0x0000, 0x0800, CRC(7dff3f9f) SHA1(bbf4e036d025fe8179b053d639f9b8ad401e6e68) )
+	ROM_REGION( 0x10000, "mcu", 0 ) /* M-Chip (i8x42 internal ROM) */
+	ROM_LOAD( "b44-8742.mcu", 0x0000, 0x0800, CRC(7dff3f9f) SHA1(bbf4e036d025fe8179b053d639f9b8ad401e6e68) ) /* B44 // 09 is the label? what is the mask number under the label? maybe Taito M-011? last digit is definitely 1 */
 
 	ROM_REGION( 0x100000, "gfx1", 0 )
 	ROM_LOAD( "b44-01.a13", 0x00000, 0x20000, CRC(aae7b3d5) SHA1(52809ea22d98811ece2fb27e80db6ddf4fbacb07) )
@@ -2382,17 +2370,27 @@ ROM_START( chukataij )
 	ROM_LOAD( "b44-06.a05", 0xa0000, 0x20000, CRC(269978a8) SHA1(aef7b8d3d00dcc4201e0a1e28026f6f1bdafd0b7) )
 	ROM_LOAD( "b44-07.a04", 0xc0000, 0x20000, CRC(3e0e737e) SHA1(f8d62c7b69c79da9df7ef5ce454060d3645e5884) )
 	ROM_LOAD( "b44-08.a02", 0xe0000, 0x20000, CRC(6cb1e8fc) SHA1(4ab0c2cce1de2616044a9bfb9bf17f95a49baffd) )
+
+	ROM_REGION( 0x10000, "pal", 0 ) /* these are shared with extermination except d9 */
+	ROM_LOAD( "b06-101.pal16l8a.d9.jed", 0x00000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-11.pal16l8a.d6.jed", 0x01000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-12.pal16l8a.c3.jed", 0x02000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-13.pal16l8a.c2.jed", 0x03000, 0x01000, NO_DUMP)
 ROM_END
 
+/*An undumped set of chuka taisen exists with all roms in the b44-14
+thru b44-25 number range and 27c1000d gfx roms, AND COLOR PROMS, using the older p0-025-a pcb
+This set, unlike the others, does use the b06-10.pal16l8a.d9.jed "older" pal rather than the 'newer' b06-101.pal16l8a.d9.jed pal.
+*/
+
 
 /*
 The New Zealand Story
 Taito, 1988
 
-This PCB runs on Taito/Seta hardware.
-
 PCB Layout ("New style PCB" with 3x z80 and no M-chip, and a daughterboard w/roms and z80)
 ----------
+The tnzs PCB has a sticker label which says "M6100409A // N.Z.LAND STORY"
 
 M6100356A (on PCB)
 P0-043A (Seta number; on PCB)
@@ -2458,7 +2456,6 @@ Notes:
 */
 
 /* tnzs - new style PCB sets */
-
 ROM_START( tnzs )
 	ROM_REGION( 0x20000, "maincpu", 0 ) /* 64k + bankswitch areas for the first CPU */
 	ROM_LOAD( "b53-24.u1",   0x00000, 0x20000, CRC(d66824c6) SHA1(fd381ac0dc52ce670c3fde320ea60a209e288a52) )
@@ -2480,7 +2477,10 @@ ROM_START( tnzs )
 	ROM_LOAD( "b53-21.ic14",  0xe0000, 0x20000, CRC(9800c54d) SHA1(761647177d621ac2cdd8b009876eed35809f3c92) ) /* Also labeled as U46U */
 
 	ROM_REGION( 0x10000, "pal", 0 )
-	ROM_LOAD( "b53-15.pal16l8a.subpcb.ic6.jed", 0x00000, 0x01000, NO_DUMP) // on sub pcb
+	/* these are shared with extermination except for the subpcb pal */
+	ROM_LOAD( "b06-13.pal16l8a.f2.jed",  0x01000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-101.pal16l8a.i2.jed", 0x02000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b53-15.pal16l8a.subpcb.ic6.jed", 0x03000, 0x01000, NO_DUMP) // on sub pcb
 ROM_END
 
 ROM_START( tnzsj )
@@ -2504,7 +2504,10 @@ ROM_START( tnzsj )
 	ROM_LOAD( "b53-21.ic14",  0xe0000, 0x20000, CRC(9800c54d) SHA1(761647177d621ac2cdd8b009876eed35809f3c92) ) /* Also labeled as U46U */
 
 	ROM_REGION( 0x10000, "pal", 0 )
-	ROM_LOAD( "b53-15.pal16l8a.subpcb.ic6.jed", 0x00000, 0x01000, NO_DUMP) // on sub pcb
+	/* these are shared with extermination except for the subpcb pal */
+	ROM_LOAD( "b06-13.pal16l8a.f2.jed",  0x01000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-101.pal16l8a.i2.jed", 0x02000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b53-15.pal16l8a.subpcb.ic6.jed", 0x03000, 0x01000, NO_DUMP) // on sub pcb
 ROM_END
 
 /* tnzs - old style PCB sets
@@ -2516,17 +2519,46 @@ Taito ID: K1100356A
           MAIN PCB
 Seta ID: P0-041A
 */
-/* This pcb is similar but not identical to the Chuka Taisen pcb;
-   There is an M-chip i8742 (with Taito silkscreen) and no 3rd z80.
-   There is no daughter-pcb like the later TNZS pcb has. */
+/* This pcb is derived from the Chuka Taisen,DrToppel and Arkanoid 2 pcbs, replacing the two color proms with color ram;
+   There is an M-chip i8x42 (with Taito silkscreen) and no 3rd z80.
+   There is no daughter-pcb like the later TNZS pcb has.
+   GFX Roms on the pcb are 28 pin 23C1000/TC531000 128K mask roms */
+
+ROM_START( tnzso )
+	ROM_REGION( 0x20000, "maincpu", 0 ) /* 64k + bankswitch areas for the first CPU */
+	ROM_LOAD( "b53-10.27c1001d.u32", 0x00000, 0x20000, CRC(a73745c6) SHA1(73eb38e75e08312d752332f988dc655084b4a86d) )
+
+	ROM_REGION( 0x10000, "sub", 0 ) /* 64k for the second CPU */
+	ROM_LOAD( "b53-14.u38", 0x00000, 0x10000, CRC(f269c5f1) SHA1(15e00e5bc6394f55fc6c591754e24842708f49f4) ) // World version old style PCB
+
+	ROM_REGION( 0x10000, "mcu", 0 ) /* M-Chip (i8x42 internal ROM) */
+	ROM_LOAD( "b53-09.u46", 0x0000, 0x0800, CRC(a4bfce19) SHA1(9340862d5bdc1ad4799dc92cae9bce1428b47478) )
+
+	ROM_REGION( 0x100000, "gfx1", 0 )
+	ROM_LOAD( "b53-08.u8",   0x00000, 0x20000, CRC(c3519c2a) SHA1(30fe7946fbc95ab6b3ccb6944fb24bf47bf3d743) )
+	ROM_LOAD( "b53-07.u7",   0x20000, 0x20000, CRC(2bf199e8) SHA1(4ed73e4f00ae2f5f4028a0ea5ae3cd238863a370) )
+	ROM_LOAD( "b53-06.u6",   0x40000, 0x20000, CRC(92f35ed9) SHA1(5fdd8d6ddbb7be9887af3c8dea9ad3b58c4e86f9) )
+	ROM_LOAD( "b53-05.u5",   0x60000, 0x20000, CRC(edbb9581) SHA1(539396a01ca0b69455f000d446759b232530b542) )
+	ROM_LOAD( "b53-04.u4",   0x80000, 0x20000, CRC(59d2aef6) SHA1(b657b7603c3eb5f169000d38497ebb93f26f7832) )
+	ROM_LOAD( "b53-03.u3",   0xa0000, 0x20000, CRC(74acfb9b) SHA1(90b544ed7ede7565660bdd13c94c15c54423cda9) )
+	ROM_LOAD( "b53-02.u2",   0xc0000, 0x20000, CRC(095d0dc0) SHA1(ced2937d0594fa00ae344a4e3a3cba23772dc160) )
+	ROM_LOAD( "b53-01.u1",   0xe0000, 0x20000, CRC(9800c54d) SHA1(761647177d621ac2cdd8b009876eed35809f3c92) )
+
+	ROM_REGION( 0x10000, "pal", 0 ) /* these are probably shared with extermination except for u35 */
+	ROM_LOAD( "b06-12.pal16l8a.u26.jed", 0x00000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-13.pal16l8a.u25.jed", 0x01000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b53-12.pal16l8a.u35.jed", 0x02000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-101.pal16l8a.u36.jed", 0x03000, 0x01000, NO_DUMP)
+ROM_END
+
 ROM_START( tnzsjo )
 	ROM_REGION( 0x20000, "maincpu", 0 ) /* 64k + bankswitch areas for the first CPU */
 	ROM_LOAD( "b53-10.27c1001d.u32", 0x00000, 0x20000, CRC(a73745c6) SHA1(73eb38e75e08312d752332f988dc655084b4a86d) )
 
 	ROM_REGION( 0x10000, "sub", 0 ) /* 64k for the second CPU */
-	ROM_LOAD( "b53-11.27c512.u38", 0x00000, 0x10000, CRC(9784d443) SHA1(bc3647aac9974031dbe4898417fbaa99841f9548) )
+	ROM_LOAD( "b53-11.27c512.u38", 0x00000, 0x10000, CRC(9784d443) SHA1(bc3647aac9974031dbe4898417fbaa99841f9548) ) // Japan version old style PCB
 
-	ROM_REGION( 0x10000, "mcu", 0 ) /* M-Chip (i8742 internal ROM) */
+	ROM_REGION( 0x10000, "mcu", 0 ) /* M-Chip (i8x42 internal ROM) */
 	ROM_LOAD( "b53-09.u46", 0x0000, 0x0800, CRC(a4bfce19) SHA1(9340862d5bdc1ad4799dc92cae9bce1428b47478) )
 
 	ROM_REGION( 0x100000, "gfx1", 0 )
@@ -2552,9 +2584,9 @@ ROM_START( tnzsuo )
 	ROM_LOAD( "b53-10.27c1001d.u32", 0x00000, 0x20000, CRC(a73745c6) SHA1(73eb38e75e08312d752332f988dc655084b4a86d) )
 
 	ROM_REGION( 0x10000, "sub", 0 ) /* 64k for the second CPU */
-	ROM_LOAD( "b53-13.27c512.u38", 0x00000, 0x10000, CRC(c09f4d28) SHA1(f1fd3202869738e17abcbb757f9ce7260707dd3d) )
+	ROM_LOAD( "b53-13.27c512.u38", 0x00000, 0x10000, CRC(c09f4d28) SHA1(f1fd3202869738e17abcbb757f9ce7260707dd3d) ) // US version old style PCB
 
-	ROM_REGION( 0x10000, "mcu", 0 ) /* M-Chip (i8742 internal ROM) */
+	ROM_REGION( 0x10000, "mcu", 0 ) /* M-Chip (i8x42 internal ROM) */
 	ROM_LOAD( "b53-09.u46", 0x0000, 0x0800, CRC(a4bfce19) SHA1(9340862d5bdc1ad4799dc92cae9bce1428b47478) )
 
 	ROM_REGION( 0x100000, "gfx1", 0 )
@@ -2574,14 +2606,14 @@ ROM_START( tnzsuo )
 	ROM_LOAD( "b06-101.pal16l8a.u36.jed", 0x03000, 0x01000, NO_DUMP)
 ROM_END
 
-	ROM_START( tnzso )
+ROM_START( tnzsoa ) // is this a legit set, or a hack, or a near-final (later than tnzsop below) prototype?
 	ROM_REGION( 0x20000, "maincpu", 0 ) /* 64k + bankswitch areas for the first CPU */
 	ROM_LOAD( "b53-unknown.27c1001d.u32", 0x00000, 0x20000, CRC(edf3b39e) SHA1(be221c99e50795d569611dba454c3954a259a859) ) // ROM LABEL FOR THIS SET IS UNKNOWN
 
 	ROM_REGION( 0x10000, "sub", 0 ) /* 64k for the second CPU */
 	ROM_LOAD( "b53-unknown.27c512.u38", 0x00000, 0x10000, CRC(60340d63) SHA1(12a26d19dc8e407e502f25617a5a4c9cea131ce2) ) // ROM LABEL FOR THIS SET IS UNKNOWN
 
-	ROM_REGION( 0x10000, "mcu", 0 ) /* M-Chip (i8742 internal ROM) */
+	ROM_REGION( 0x10000, "mcu", 0 ) /* M-Chip (i8x42 internal ROM) */
 	ROM_LOAD( "b53-09.u46", 0x0000, 0x0800, CRC(a4bfce19) SHA1(9340862d5bdc1ad4799dc92cae9bce1428b47478) )
 
 	ROM_REGION( 0x100000, "gfx1", 0 )
@@ -2603,31 +2635,36 @@ ROM_END
 	ROM_LOAD( "b06-101.pal16l8a.u36.jed", 0x03000, 0x01000, NO_DUMP)
 ROM_END
 
-ROM_START( tnzsop ) // prototype/location test version?
+/* This is a prototype CA403001A PCB (Seta: P0-041-1), and is ALMOST but not exactly the same as the K1100356A/J1100156A (Seta: P0-041A) 'tnzsuo/tnzsjo/arkanoid2/etc' pcb above:
+This pcb uses 32-pin 27c1000d eproms for the 8 gfx roms, and the final K1100356A/J1100156A pcb uses 28 pin 23c1000 mask roms instead. Some capacitors near the jamma connector were moved as well.
+No other obviously evident routing/wiring changes are present.
+This type of pcb might have been used for in-house testing of all the games on this hardware.
+*/
+ROM_START( tnzsop ) // prototype (location test?) version; has different rom labels, and the Seta X1-001 chip has prototype markings revealing it was fabbed by Yamaha, as 'YM3906'
 	ROM_REGION( 0x20000, "maincpu", 0 ) /* 64k + bankswitch areas for the first CPU */
-	ROM_LOAD( "ns_c-11.27c1001d.u32", 0x00000, 0x20000, CRC(3c1dae7b) SHA1(0004fccc171714c80565326f8690f9662c5b75d9) )
+	ROM_LOAD( "c-11__6-24__1959h.d27c1000d-15.u32", 0x00000, 0x20000, CRC(3c1dae7b) SHA1(0004fccc171714c80565326f8690f9662c5b75d9) ) // Labeled as PCB location, date of 6/24 & checksum - NEC D271000d  eprom
 
 	ROM_REGION( 0x10000, "sub", 0 ) /* 64k for the second CPU */
-	ROM_LOAD( "ns_e-3.27c512.u38", 0x00000, 0x10000, CRC(c7662e96) SHA1(be28298bfde4e3867cfe75633ffb0f8611dbbd8b) )
+	ROM_LOAD( "e-3__6-24__c4ach.tmm27512d-20.u38", 0x00000, 0x10000, CRC(c7662e96) SHA1(be28298bfde4e3867cfe75633ffb0f8611dbbd8b) ) // Labeled as PCB location, date of 6/24 & checksum - TMM27512D  eprom
 
-	ROM_REGION( 0x10000, "mcu", 0 ) /* M-Chip (i8742 internal ROM) */
-	ROM_LOAD( "b53-09.u46", 0x0000, 0x0800, CRC(a4bfce19) SHA1(9340862d5bdc1ad4799dc92cae9bce1428b47478) )
+	ROM_REGION( 0x10000, "mcu", 0 ) /* M-Chip (i8x42 internal ROM) */
+	ROM_LOAD( "b8042h__'88-6-22__0fcc.d8742.u46", 0x0000, 0x0800, CRC(a4bfce19) SHA1(9340862d5bdc1ad4799dc92cae9bce1428b47478) ) // Dated  '88/6/22 with checksum - Intel D8742 MCU
 
 	ROM_REGION( 0x100000, "gfx1", 0 )
-	ROM_LOAD( "ns_a13.rom.u8",   0x00000, 0x20000, CRC(7e0bd5bb) SHA1(95dfb00ec915778e02d8bfa996735ab817191adc) )
-	ROM_LOAD( "ns_a12.rom.u7",   0x20000, 0x20000, CRC(95880726) SHA1(f4fdedd23e80a6ccf32f737ab4bc57f9fc0925be) )
-	ROM_LOAD( "ns_a10.rom.u6",   0x40000, 0x20000, CRC(2bc4c053) SHA1(cd7668a7733e5e80c2c566d0cf63c4310e5743b4) )
-	ROM_LOAD( "ns_a08.rom.u5",   0x60000, 0x20000, CRC(8ff8d88c) SHA1(31977e39ad048a077e9b5bd712ff66b14a466d27) )
-	ROM_LOAD( "ns_a07.rom.u4",   0x80000, 0x20000, CRC(291bcaca) SHA1(4f659a0cd2ff6b4ec04ab95ee8a670222c402c2b) )
-	ROM_LOAD( "ns_a05.rom.u3",   0xa0000, 0x20000, CRC(6e762e20) SHA1(66731fe4053b9c09bc9c95d10aba212db08b4636) )
-	ROM_LOAD( "ns_a04.rom.u2",   0xc0000, 0x20000, CRC(e1fd1b9d) SHA1(6027491b927c2ab9c77fbf8895da1abcfbe32d62) )
-	ROM_LOAD( "ns_a02.rom.u1",   0xe0000, 0x20000, CRC(2ab06bda) SHA1(2b208b564e55c258665e1f66b26fe14a6c68eb96) )
+	ROM_LOAD( "a13__03e8.d27c1000d-15.a13",  0x00000, 0x20000, CRC(7e0bd5bb) SHA1(95dfb00ec915778e02d8bfa996735ab817191adc) ) // labels contain the PCB location & checksum
+	ROM_LOAD( "a12__f4ec.d27c1000d-15.a12",  0x20000, 0x20000, CRC(95880726) SHA1(f4fdedd23e80a6ccf32f737ab4bc57f9fc0925be) ) // PCB CA403001A did NOT have silkscreened U1 - U8 labels
+	ROM_LOAD( "a10__f2b5.d27c1000d-15.a10",  0x40000, 0x20000, CRC(2bc4c053) SHA1(cd7668a7733e5e80c2c566d0cf63c4310e5743b4) ) // PCB also labeled as P0-041-1
+	ROM_LOAD( "a08__bd49.d27c1000d-15.a8",   0x60000, 0x20000, CRC(8ff8d88c) SHA1(31977e39ad048a077e9b5bd712ff66b14a466d27) )
+	ROM_LOAD( "a07__d5f3.d27c1000d-15.a7",   0x80000, 0x20000, CRC(291bcaca) SHA1(4f659a0cd2ff6b4ec04ab95ee8a670222c402c2b) )
+	ROM_LOAD( "a05__662a.d27c1000d-15.a5",   0xa0000, 0x20000, CRC(6e762e20) SHA1(66731fe4053b9c09bc9c95d10aba212db08b4636) )
+	ROM_LOAD( "a04__0c21.d27c1000d-15.a4",   0xc0000, 0x20000, CRC(e1fd1b9d) SHA1(6027491b927c2ab9c77fbf8895da1abcfbe32d62) )
+	ROM_LOAD( "a02__904f.d27c1000d-15.a2",   0xe0000, 0x20000, CRC(2ab06bda) SHA1(2b208b564e55c258665e1f66b26fe14a6c68eb96) )
 
-	ROM_REGION( 0x10000, "pal", 0 ) /* PALS not directly observed on this board but assumed to exist */
+	ROM_REGION( 0x10000, "pal", 0 )
 	/* these are probably shared with extermination except for u35 */
-	ROM_LOAD( "b06-12.pal16l8a.u26.jed", 0x00000, 0x01000, NO_DUMP)
-	ROM_LOAD( "b06-13.pal16l8a.u25.jed", 0x01000, 0x01000, NO_DUMP)
-	ROM_LOAD( "b53-12.pal16l8a.u35.jed", 0x02000, 0x01000, NO_DUMP) // likely has a different name on the proto pcb...
+	ROM_LOAD( "b06-12.pal16l8a.u26.jed",  0x00000, 0x01000, NO_DUMP)
+	ROM_LOAD( "b06-13.pal16l8a.u25.jed",  0x01000, 0x01000, NO_DUMP)
+	ROM_LOAD( "st-6.pal16l8a.u35.jed",    0x02000, 0x01000, NO_DUMP)
 	ROM_LOAD( "b06-101.pal16l8a.u36.jed", 0x03000, 0x01000, NO_DUMP)
 ROM_END
 
@@ -2713,64 +2750,65 @@ ROM_END
 
 ROM_START( insectx )
 	ROM_REGION( 0x20000, "maincpu", 0 ) /* 64k + bankswitch areas for the first CPU */
-	ROM_LOAD( "b97-03.u32", 0x00000, 0x20000, CRC(18eef387) SHA1(b22633930d39be1e72fbd5b080972122da3cb3ef) )
+	ROM_LOAD( "b97__03.u32", 0x00000, 0x20000, CRC(18eef387) SHA1(b22633930d39be1e72fbd5b080972122da3cb3ef) )
 
 	ROM_REGION( 0x10000, "sub", 0 ) /* 64k for the second CPU */
-	ROM_LOAD( "b97-07.u38", 0x00000, 0x10000, CRC(324b28c9) SHA1(db77a4ac60196d0f0f35dbc5c951ec29d6392463) ) /* Label is B97 07* with an astrix */
+	ROM_LOAD( "b97__07.u38", 0x00000, 0x10000, CRC(324b28c9) SHA1(db77a4ac60196d0f0f35dbc5c951ec29d6392463) ) /* Label is B97 07* with an asterisk */
 
 	ROM_REGION( 0x100000, "gfx1", 0 ) /* Mask roms */
-	ROM_LOAD( "b97-01.u1", 0x00000, 0x80000, CRC(d00294b1) SHA1(f43a4f7d13193ddbbcdef71a5085c1db0fc062d4) )
-	ROM_LOAD( "b97-02.u2", 0x80000, 0x80000, CRC(db5a7434) SHA1(71fac872b19a13a7ad25c8ad895c322ec9573fdc) )
+	ROM_LOAD( "b97__01.u1", 0x00000, 0x80000, CRC(d00294b1) SHA1(f43a4f7d13193ddbbcdef71a5085c1db0fc062d4) )
+	ROM_LOAD( "b97__02.u2", 0x80000, 0x80000, CRC(db5a7434) SHA1(71fac872b19a13a7ad25c8ad895c322ec9573fdc) )
 ROM_END
 
 ROM_START( insectxj )
 	ROM_REGION( 0x20000, "maincpu", 0 ) /* 64k + bankswitch areas for the first CPU */
-	ROM_LOAD( "b97-03.u32", 0x00000, 0x20000, CRC(18eef387) SHA1(b22633930d39be1e72fbd5b080972122da3cb3ef) )
+	ROM_LOAD( "b97__03.u32", 0x00000, 0x20000, CRC(18eef387) SHA1(b22633930d39be1e72fbd5b080972122da3cb3ef) )
 
 	ROM_REGION( 0x10000, "sub", 0 ) /* 64k for the second CPU */
-	ROM_LOAD( "b97-04.u38", 0x00000, 0x10000, CRC(dc4549e5) SHA1(9920f7c12e047ee165418d33b3add51ea615df7e) ) /* Label is B97 04* with an astrix */
+	ROM_LOAD( "b97__04.u38", 0x00000, 0x10000, CRC(dc4549e5) SHA1(9920f7c12e047ee165418d33b3add51ea615df7e) ) /* Label is B97 04* with an asterisk */
 
 	ROM_REGION( 0x100000, "gfx1", 0 ) /* Mask roms */
-	ROM_LOAD( "b97-01.u1", 0x00000, 0x80000, CRC(d00294b1) SHA1(f43a4f7d13193ddbbcdef71a5085c1db0fc062d4) )
-	ROM_LOAD( "b97-02.u2", 0x80000, 0x80000, CRC(db5a7434) SHA1(71fac872b19a13a7ad25c8ad895c322ec9573fdc) )
+	ROM_LOAD( "b97__01.u1", 0x00000, 0x80000, CRC(d00294b1) SHA1(f43a4f7d13193ddbbcdef71a5085c1db0fc062d4) )
+	ROM_LOAD( "b97__02.u2", 0x80000, 0x80000, CRC(db5a7434) SHA1(71fac872b19a13a7ad25c8ad895c322ec9573fdc) )
 ROM_END
 
 
 //    YEAR, NAME,      PARENT,   MACHINE,  INPUT,    INIT,     MONITOR,COMPANY,FULLNAME,FLAGS
-GAME( 1987, plumppop,  0,        drtoppel, plumppop, tnzs_state,    plumpop,  ROT0,   "Taito Corporation", "Plump Pop (Japan)", MACHINE_SUPPORTS_SAVE )
+GAME( 1987, plumppop,  0,        extrmatn, plumppop, driver_device, 0,  ROT0,   "Taito Corporation", "Plump Pop (Japan)", MACHINE_SUPPORTS_SAVE )
 GAME( 1992, jpopnics,  0,        jpopnics, jpopnics, driver_device, 0,        ROT0,   "Nics",              "Jumping Pop (Nics, Korean hack of Plump Pop)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
 
-GAME( 1987, extrmatn,  0,        arknoid2, extrmatn, tnzs_state,    extrmatn, ROT270, "Taito Corporation Japan",                         "Extermination (World)", MACHINE_SUPPORTS_SAVE )
-GAME( 1987, extrmatnu, extrmatn, arknoid2, extrmatn, tnzs_state,    extrmatn, ROT270, "Taito (World Games license)",                     "Extermination (US, World Games)", MACHINE_SUPPORTS_SAVE )
-GAME( 1987, extrmatnur,extrmatn, arknoid2, extrmatn, tnzs_state,    extrmatn, ROT270, "Taito America Corporation (Romstar license)",     "Extermination (US, Romstar)", MACHINE_SUPPORTS_SAVE )
-GAME( 1987, extrmatnj, extrmatn, arknoid2, extrmatn, tnzs_state,    extrmatn, ROT270, "Taito Corporation",                               "Extermination (Japan)", MACHINE_SUPPORTS_SAVE )
-
-GAME( 1987, arknoid2,  0,        arknoid2, arknoid2, tnzs_state,    arknoid2, ROT270, "Taito Corporation Japan",                     "Arkanoid - Revenge of DOH (World)", MACHINE_SUPPORTS_SAVE )
-GAME( 1987, arknoid2u, arknoid2, arknoid2, arknid2u, tnzs_state,    arknoid2, ROT270, "Taito America Corporation (Romstar license)", "Arkanoid - Revenge of DOH (US)", MACHINE_SUPPORTS_SAVE )
-GAME( 1987, arknoid2j, arknoid2, arknoid2, arknid2u, tnzs_state,    arknoid2, ROT270, "Taito Corporation",                           "Arkanoid - Revenge of DOH (Japan)", MACHINE_SUPPORTS_SAVE )
-GAME( 1987, arknoid2b, arknoid2, arknoid2, arknid2u, tnzs_state,    arknoid2, ROT270, "bootleg",                                     "Arkanoid - Revenge of DOH (Japan bootleg)", MACHINE_SUPPORTS_SAVE )
-
-GAME( 1987, drtoppel,  0,        drtoppel, drtoppel, tnzs_state,    drtoppel, ROT90,  "Kaneko / Taito Corporation Japan",   "Dr. Toppel's Adventure (World)", MACHINE_SUPPORTS_SAVE ) /* Possible region hack */
-GAME( 1987, drtoppelu, drtoppel, drtoppel, drtopplu, tnzs_state,    drtoppel, ROT90,  "Kaneko / Taito America Corporation", "Dr. Toppel's Adventure (US)", MACHINE_SUPPORTS_SAVE ) /* Possible region hack */
-GAME( 1987, drtoppelj, drtoppel, drtoppel, drtopplu, tnzs_state,    drtoppel, ROT90,  "Kaneko / Taito Corporation",         "Dr. Toppel's Tankentai (Japan)", MACHINE_SUPPORTS_SAVE )
-
-GAME( 1988, kageki,    0,        kageki,   kageki,   tnzs_state,    kageki,   ROT90,  "Kaneko / Taito America Corporation (Romstar license)", "Kageki (US)", MACHINE_SUPPORTS_SAVE )
-GAME( 1988, kagekij,   kageki,   kageki,   kagekij,  tnzs_state,    kageki,   ROT90,  "Kaneko / Taito Corporation",                           "Kageki (Japan)", MACHINE_SUPPORTS_SAVE )
-GAME( 1992, kagekih,   kageki,   kageki,   kageki,   tnzs_state,    kageki,   ROT90,  "hack",                                                 "Kageki (hack)", MACHINE_SUPPORTS_SAVE ) // date is hacked at least, might also be a Japan set hacked to show english
-
-GAME( 1988, chukatai,  0,        tnzs,     chukatai, tnzs_state,    chukatai, ROT0,   "Taito Corporation Japan",   "Chuka Taisen (World)", MACHINE_SUPPORTS_SAVE ) /* Possible region hack */
-GAME( 1988, chukataiu, chukatai, tnzs,     chukatau, tnzs_state,    chukatai, ROT0,   "Taito America Corporation", "Chuka Taisen (US)", MACHINE_SUPPORTS_SAVE ) /* Possible region hack */
-GAME( 1988, chukataij, chukatai, tnzs,     chukatau, tnzs_state,    chukatai, ROT0,   "Taito Corporation",         "Chuka Taisen (Japan)", MACHINE_SUPPORTS_SAVE )
-
-GAME( 1988, tnzs,      0,        tnzsb,    tnzs,     tnzs_state,    tnzsb,    ROT0,   "Taito Corporation Japan", "The NewZealand Story (World, new version) (newer PCB)", MACHINE_SUPPORTS_SAVE )
-GAME( 1988, tnzsj,     tnzs,     tnzsb,    tnzsj,    tnzs_state,    tnzsb,    ROT0,   "Taito Corporation",       "The NewZealand Story (Japan, new version) (newer PCB)", MACHINE_SUPPORTS_SAVE )
-GAME( 1988, tnzsjo,    tnzs,     tnzs,     tnzsjo,   tnzs_state,    tnzs,     ROT0,   "Taito Corporation",       "The NewZealand Story (Japan, old version) (older PCB)", MACHINE_SUPPORTS_SAVE )
-GAME( 1988, tnzsuo,    tnzs,     tnzs,     tnzsjo,   tnzs_state,    tnzs,     ROT0,   "Taito America Corporation", "The NewZealand Story (US, old version) (older PCB)",    MACHINE_SUPPORTS_SAVE )
-GAME( 1988, tnzso,     tnzs,     tnzs,     tnzsop,   tnzs_state,    tnzs,     ROT0,   "Taito Corporation Japan", "The NewZealand Story (World, old version) (older PCB)", MACHINE_SUPPORTS_SAVE )
-GAME( 1988, tnzsop,    tnzs,     tnzs,     tnzsop,   tnzs_state,    tnzs,     ROT0,   "Taito Corporation Japan", "The NewZealand Story (World, prototype?) (older PCB)", MACHINE_SUPPORTS_SAVE )
-
-GAME( 1988, kabukiz,   0,        kabukiz,  kabukiz,  tnzs_state,    kabukiz,  ROT0,   "Kaneko / Taito Corporation Japan", "Kabuki-Z (World)", MACHINE_SUPPORTS_SAVE )
-GAME( 1988, kabukizj,  kabukiz,  kabukiz,  kabukizj, tnzs_state,    kabukiz,  ROT0,   "Kaneko / Taito Corporation",       "Kabuki-Z (Japan)", MACHINE_SUPPORTS_SAVE )
-
-GAME( 1989, insectx,   0,        insectx,  insectx,  tnzs_state,    insectx,  ROT0,   "Taito Corporation Japan", "Insector X (World)", MACHINE_SUPPORTS_SAVE )
-GAME( 1989, insectxj,  insectx,  insectx,  insectxj, tnzs_state,    insectx,  ROT0,   "Taito Corporation",       "Insector X (Japan)", MACHINE_SUPPORTS_SAVE )
+GAME( 1987, extrmatn,  0,        extrmatn, extrmatn, driver_device, 0, ROT270, "Taito Corporation Japan",                         "Extermination (World)", MACHINE_SUPPORTS_SAVE )
+GAME( 1987, extrmatnu, extrmatn, extrmatn, extrmatn, driver_device, 0, ROT270, "Taito (World Games license)",                     "Extermination (US, World Games)", MACHINE_SUPPORTS_SAVE )
+GAME( 1987, extrmatnur,extrmatn, extrmatn, extrmatn, driver_device, 0, ROT270, "Taito America Corporation (Romstar license)",     "Extermination (US, Romstar)", MACHINE_SUPPORTS_SAVE )
+GAME( 1987, extrmatnj, extrmatn, extrmatn, extrmatn, driver_device, 0, ROT270, "Taito Corporation",                               "Extermination (Japan)", MACHINE_SUPPORTS_SAVE )
+
+GAME( 1987, arknoid2,  0,        arknoid2, arknoid2, driver_device, 0, ROT270, "Taito Corporation Japan",                     "Arkanoid - Revenge of DOH (World)", MACHINE_SUPPORTS_SAVE )
+GAME( 1987, arknoid2u, arknoid2, arknoid2, arknid2u, driver_device, 0, ROT270, "Taito America Corporation (Romstar license)", "Arkanoid - Revenge of DOH (US)", MACHINE_SUPPORTS_SAVE )
+GAME( 1987, arknoid2j, arknoid2, arknoid2, arknid2u, driver_device, 0, ROT270, "Taito Corporation",                           "Arkanoid - Revenge of DOH (Japan)", MACHINE_SUPPORTS_SAVE )
+GAME( 1987, arknoid2b, arknoid2, arknoid2, arknid2u, driver_device, 0, ROT270, "bootleg",                                     "Arkanoid - Revenge of DOH (Japan bootleg)", MACHINE_SUPPORTS_SAVE )
+
+GAME( 1987, drtoppel,  0,        extrmatn, drtoppel, driver_device, 0, ROT90,  "Kaneko / Taito Corporation Japan",   "Dr. Toppel's Adventure (World)", MACHINE_SUPPORTS_SAVE ) /* Possible region hack */
+GAME( 1987, drtoppelu, drtoppel, extrmatn, drtopplu, driver_device, 0, ROT90,  "Kaneko / Taito America Corporation", "Dr. Toppel's Adventure (US)", MACHINE_SUPPORTS_SAVE ) /* Possible region hack */
+GAME( 1987, drtoppelj, drtoppel, extrmatn, drtopplu, driver_device, 0, ROT90,  "Kaneko / Taito Corporation",         "Dr. Toppel's Tankentai (Japan)", MACHINE_SUPPORTS_SAVE )
+
+GAME( 1988, kageki,    0,        kageki,   kageki,   driver_device, 0, ROT90,  "Kaneko / Taito America Corporation (Romstar license)", "Kageki (US)", MACHINE_SUPPORTS_SAVE )
+GAME( 1988, kagekij,   kageki,   kageki,   kagekij,  driver_device, 0, ROT90,  "Kaneko / Taito Corporation",                           "Kageki (Japan)", MACHINE_SUPPORTS_SAVE )
+GAME( 1992, kagekih,   kageki,   kageki,   kageki,   driver_device, 0, ROT90,  "hack",                                                 "Kageki (hack)", MACHINE_SUPPORTS_SAVE ) // date is hacked at least, might also be a Japan set hacked to show english
+
+GAME( 1988, chukatai,  0,        tnzs,     chukatai, driver_device, 0, ROT0,   "Taito Corporation Japan",   "Chuka Taisen (World)", MACHINE_SUPPORTS_SAVE ) /* Possible region hack */
+GAME( 1988, chukataiu, chukatai, tnzs,     chukatau, driver_device, 0, ROT0,   "Taito America Corporation", "Chuka Taisen (US)", MACHINE_SUPPORTS_SAVE ) /* Possible region hack */
+GAME( 1988, chukataij, chukatai, tnzs,     chukatau, driver_device, 0, ROT0,   "Taito Corporation",         "Chuka Taisen (Japan)", MACHINE_SUPPORTS_SAVE )
+
+GAME( 1988, tnzs,      0,        tnzsb,    tnzs,     driver_device, 0,  ROT0,   "Taito Corporation Japan",   "The NewZealand Story (World, new version) (newer PCB)", MACHINE_SUPPORTS_SAVE )
+GAME( 1988, tnzsj,     tnzs,     tnzsb,    tnzsj,    driver_device, 0,  ROT0,   "Taito Corporation",         "The NewZealand Story (Japan, new version) (newer PCB)", MACHINE_SUPPORTS_SAVE )
+GAME( 1988, tnzso,     tnzs,     tnzs,     tnzsop,   driver_device, 0,  ROT0,   "Taito Corporation Japan",   "The NewZealand Story (World, old version) (older PCB)", MACHINE_SUPPORTS_SAVE )
+GAME( 1988, tnzsjo,    tnzs,     tnzs,     tnzsjo,   driver_device, 0,  ROT0,   "Taito Corporation",         "The NewZealand Story (Japan, old version) (older PCB)", MACHINE_SUPPORTS_SAVE )
+GAME( 1988, tnzsuo,    tnzs,     tnzs,     tnzsjo,   driver_device, 0,  ROT0,   "Taito America Corporation", "The NewZealand Story (US, old version) (older PCB)",    MACHINE_SUPPORTS_SAVE )
+GAME( 1988, tnzsoa,    tnzs,     tnzs,     tnzsop,   driver_device, 0,  ROT0,   "Taito Corporation Japan",   "The NewZealand Story (World, unknown version) (older PCB)", MACHINE_SUPPORTS_SAVE )
+GAME( 1988, tnzsop,    tnzs,     tnzs,     tnzsop,   driver_device, 0,  ROT0,   "Taito Corporation Japan",   "The NewZealand Story (World, prototype) (older PCB)", MACHINE_SUPPORTS_SAVE )
+
+GAME( 1988, kabukiz,   0,        kabukiz,  kabukiz,  driver_device, 0,  ROT0,   "Kaneko / Taito Corporation Japan", "Kabuki-Z (World)", MACHINE_SUPPORTS_SAVE )
+GAME( 1988, kabukizj,  kabukiz,  kabukiz,  kabukizj, driver_device, 0,  ROT0,   "Kaneko / Taito Corporation",       "Kabuki-Z (Japan)", MACHINE_SUPPORTS_SAVE )
+
+GAME( 1989, insectx,   0,        insectx,  insectx,  driver_device, 0,  ROT0,   "Taito Corporation Japan", "Insector X (World)", MACHINE_SUPPORTS_SAVE )
+GAME( 1989, insectxj,  insectx,  insectx,  insectxj, driver_device, 0,  ROT0,   "Taito Corporation",       "Insector X (Japan)", MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/drivers/toaplan1.cpp b/src/mame/drivers/toaplan1.cpp
index 9a916bf..cd89cc3 100644
--- a/src/mame/drivers/toaplan1.cpp
+++ b/src/mame/drivers/toaplan1.cpp
@@ -603,14 +603,6 @@ Stephh's and AWJ's notes (based on the games M68000 and Z80 code and some tests)
   - Sound routines at 0x01792c and 0x0179ba.
 
 
-To Do:
-    Add support for HD647180 (Z180) sound CPUs (once their internal ROMS are dumped).
-    These are:
-        Fire Shark / Same! Same! Same!
-        Vimana
-    In the meantime, it can be interesting to simulate the basic communications (coinage and credits)
-    between the M68000 and the Z180.  [stephh]
-
 ***************************************************************************/
 
 #include "emu.h"
@@ -756,7 +748,7 @@ static ADDRESS_MAP_START( samesame_main_map, AS_PROGRAM, 16, toaplan1_state )
 	AM_RANGE(0x140008, 0x140009) AM_READ_PORT("SYSTEM")
 	AM_RANGE(0x14000a, 0x14000b) AM_READ(samesame_port_6_word_r)    /* Territory, and MCU ready */
 	AM_RANGE(0x14000c, 0x14000d) AM_WRITE(samesame_coin_w)  /* Coin counter/lockout */
-//  AM_RANGE(0x14000e, 0x14000f) AM_WRITE(samesame_mcu_w)   /* Commands sent to HD647180 */
+	AM_RANGE(0x14000e, 0x14000f) AM_WRITE(samesame_mcu_w)   /* Commands sent to HD647180 */
 	AM_RANGE(0x180000, 0x180001) AM_WRITE(toaplan1_bcu_flipscreen_w)
 	AM_RANGE(0x180002, 0x180003) AM_READWRITE(toaplan1_tileram_offs_r, toaplan1_tileram_offs_w)
 	AM_RANGE(0x180004, 0x180007) AM_READWRITE(toaplan1_tileram16_r, toaplan1_tileram16_w)
@@ -827,13 +819,7 @@ static ADDRESS_MAP_START( vimana_main_map, AS_PROGRAM, 16, toaplan1_state )
 	AM_RANGE(0x400008, 0x40000f) AM_WRITE(toaplan1_bcu_control_w)
 	AM_RANGE(0x404000, 0x4047ff) AM_RAM_WRITE(toaplan1_bgpalette_w) AM_SHARE("bgpalette")
 	AM_RANGE(0x406000, 0x4067ff) AM_RAM_WRITE(toaplan1_fgpalette_w) AM_SHARE("fgpalette")
-	AM_RANGE(0x440000, 0x440005) AM_READWRITE(vimana_mcu_r, vimana_mcu_w)  /* shared memory from 0x440000 to 0x44ffff ? */
-	AM_RANGE(0x440006, 0x440007) AM_READ_PORT("DSWA")
-	AM_RANGE(0x440008, 0x440009) AM_READ(vimana_system_port_r)   /* "SYSTEM" + coinage simulation */
-	AM_RANGE(0x44000a, 0x44000b) AM_READ_PORT("P1")
-	AM_RANGE(0x44000c, 0x44000d) AM_READ_PORT("P2")
-	AM_RANGE(0x44000e, 0x44000f) AM_READ_PORT("DSWB")
-	AM_RANGE(0x440010, 0x440011) AM_READ_PORT("TJUMP")
+	AM_RANGE(0x440000, 0x4407ff) AM_READWRITE(toaplan1_shared_r, toaplan1_shared_w) /* inputs, coins and sound handled by 647180 MCU via this space */
 	AM_RANGE(0x480000, 0x487fff) AM_RAM
 	AM_RANGE(0x4c0000, 0x4c0001) AM_WRITE(toaplan1_bcu_flipscreen_w)
 	AM_RANGE(0x4c0002, 0x4c0003) AM_READWRITE(toaplan1_tileram_offs_r, toaplan1_tileram_offs_w)
@@ -938,12 +924,90 @@ ADDRESS_MAP_END
 
 /***************************** HD647180 Memory Map **************************/
 
-static ADDRESS_MAP_START( hd647180_mem_map, AS_PROGRAM, 8, toaplan1_state )
+static ADDRESS_MAP_START( vimana_hd647180_mem_map, AS_PROGRAM, 8, toaplan1_state )
 	AM_RANGE(0x00000, 0x03fff) AM_ROM   /* Internal 16k byte ROM */
+	AM_RANGE(0x08000, 0x087ff) AM_RAM AM_SHARE("sharedram") /* 2048 bytes of shared ram w/maincpu */
 	AM_RANGE(0x0fe00, 0x0ffff) AM_RAM   /* Internal 512 byte RAM */
 ADDRESS_MAP_END
 
+static ADDRESS_MAP_START( vimana_hd647180_io_map, AS_IO, 8, toaplan1_state )
+	ADDRESS_MAP_GLOBAL_MASK(0xff)
+	// lots of low level 647180 peripherals are not emulated yet, ddr regs, timer regs etc, see comments below
+	// also see http://bitsavers.trailing-edge.com/pdf/hitachi/_dataBooks/U94_HD647180X_8-Bit_Microcontroller_Hardware_Manual_Jan88.pdf particularly page 38 (pdf page 56)
+	AM_RANGE(0x32, 0x32) AM_WRITENOP // DMA WAIT/Control register
+	AM_RANGE(0x33, 0x33) AM_WRITENOP // IL (int vector low) register
+	AM_RANGE(0x36, 0x36) AM_WRITENOP // refresh control register for RFSH pin
+	// 53: disable reg for port A
+	AM_RANGE(0x60, 0x60) AM_READ(vimana_dswb_invert_r) // read/write port A; note these inputs seem to be inverted, unlike the DSWA ones.
+	// 61: read/write port B
+	// 62: read/write port C
+	// 63: read/write port D
+	// 64: read/write port E
+	// 65: read/write port F
+	AM_RANGE(0x66, 0x66) AM_READ(vimana_tjump_invert_r) // read/write port G, bits 7 and 6 ALWAYS read as 1 due to port G being just 6 bits; note these inputs seem to be inverted, unlike the DSWA ones.
+	// 70: ddr for port A
+	AM_RANGE(0x71, 0x71) AM_WRITENOP // ddr for port B
+	AM_RANGE(0x72, 0x72) AM_WRITENOP // ddr for port C
+	AM_RANGE(0x73, 0x73) AM_WRITENOP // ddr for port D
+	AM_RANGE(0x74, 0x74) AM_WRITENOP // ddr for port E
+	AM_RANGE(0x75, 0x75) AM_WRITENOP // ddr for port F
+	AM_RANGE(0x80, 0x80) AM_READ_PORT("P1")
+	AM_RANGE(0x81, 0x81) AM_READ_PORT("P2")
+	AM_RANGE(0x82, 0x82) AM_READ_PORT("DSWA")
+	AM_RANGE(0x83, 0x83) AM_READ_PORT("SYSTEM")
+	AM_RANGE(0x84, 0x84) AM_WRITE(toaplan1_coin_w)  // Coin counter/lockout // needs verify
+	AM_RANGE(0x87, 0x87) AM_DEVREADWRITE("ymsnd", ym3812_device, status_port_r, control_port_w)
+	AM_RANGE(0x8f, 0x8f) AM_DEVREADWRITE("ymsnd", ym3812_device, read_port_r, write_port_w)
+ADDRESS_MAP_END
+
+READ8_MEMBER(toaplan1_state::vimana_dswb_invert_r)
+{
+	return ioport("DSWB")->read() ^ 0xFF;
+}
+
+READ8_MEMBER(toaplan1_state::vimana_tjump_invert_r)
+{
+	return (ioport("TJUMP")->read() ^ 0xFF)|0xC0; // high 2 bits of port G always read as 1
+}
+
+WRITE16_MEMBER(toaplan1_state::samesame_mcu_w)
+{
+	m_to_mcu = data;
+	m_cmdavailable = 1;
+};
 
+READ8_MEMBER(toaplan1_state::samesame_soundlatch_r)
+{
+	return m_to_mcu;
+};
+
+WRITE8_MEMBER(toaplan1_state::samesame_sound_done_w)
+{
+	m_to_mcu = data;
+	m_cmdavailable = 0;
+}
+
+READ8_MEMBER(toaplan1_state::samesame_cmdavailable_r)
+{
+	if (m_cmdavailable) return 0xff;
+	else return 0x00;
+};
+
+static ADDRESS_MAP_START( samesame_hd647180_mem_map, AS_PROGRAM, 8, toaplan1_state )
+	AM_RANGE(0x00000, 0x03fff) AM_ROM   /* Internal 16k byte ROM */
+	AM_RANGE(0x0fe00, 0x0ffff) AM_RAM   /* Internal 512 byte RAM */
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( samesame_hd647180_io_map, AS_IO, 8, toaplan1_state )
+	ADDRESS_MAP_GLOBAL_MASK(0xff)
+
+	AM_RANGE(0x63, 0x63) AM_READ( samesame_cmdavailable_r )
+	AM_RANGE(0xa0, 0xa0) AM_READ( samesame_soundlatch_r )
+	AM_RANGE(0xb0, 0xb0) AM_WRITE( samesame_sound_done_w )
+
+	AM_RANGE(0x80, 0x80) AM_DEVREADWRITE("ymsnd", ym3812_device, status_port_r, control_port_w)
+	AM_RANGE(0x81, 0x81) AM_DEVREADWRITE("ymsnd", ym3812_device, read_port_r, write_port_w)
+ADDRESS_MAP_END
 
 /*****************************************************************************
     Generic Input Port definitions
@@ -1645,7 +1709,7 @@ static INPUT_PORTS_START( outzonec )
 INPUT_PORTS_END
 
 
-/* verified from M68000 - coinage based on "test mode" and handled by the MCU simulation */
+/* verified from M68000 */
 static INPUT_PORTS_START( vimana )
 	PORT_INCLUDE( toaplan1_2b )
 
@@ -1656,6 +1720,12 @@ static INPUT_PORTS_START( vimana )
 
 	/* 0x44000f.b */
 	PORT_START("DSWB")
+	/* this dipswitch array is inverted either by circuitry on the pcb, or by
+	   being between portA of the 647180 and GND, relying on 647180 portA
+	   internal pin pullups?
+	   Not sure, needs tracing, but for now rather than make a new inverted
+	   TOAPLAN_DIFFICULTY macro, I've (LN) wrapped this in a function to invert
+	   it on read. See vimana_dswb_invert_r */
 	TOAPLAN_DIFFICULTY
 	PORT_DIPNAME( 0x0c, 0x00, DEF_STR( Bonus_Life ) )       /* table at 0x000998 */
 	PORT_DIPSETTING(    0x00, "70k 270k 200k+" )
@@ -1675,6 +1745,7 @@ static INPUT_PORTS_START( vimana )
 	PORT_DIPSETTING(    0x00, DEF_STR( Yes ) )
 
 	/* 0x440011.b */
+	/* same as above, this is inverted, handled by vimana_tjump_invert_r */
 	PORT_START("TJUMP")       /* Territory Jumper Block - see notes */
 	PORT_DIPNAME( 0x0f, 0x02, DEF_STR( Region ) )
 	PORT_DIPSETTING(    0x02, DEF_STR( Europe ) )
@@ -1704,7 +1775,7 @@ static INPUT_PORTS_START( vimana )
 	/* VBLANK : 0x400001.b */
 INPUT_PORTS_END
 
-/* verified from M68000 - coinage based on "test mode" and handled by the MCU simulation */
+/* verified from M68000 */
 static INPUT_PORTS_START( vimanan )
 	PORT_INCLUDE( vimana )
 
@@ -1712,6 +1783,7 @@ static INPUT_PORTS_START( vimanan )
 	/* DSWB : 0x44000f.b */
 
 	/* 0x440011.b */
+	/* same as above, this is inverted, handled by vimana_tjump_invert_r */
 	PORT_MODIFY("TJUMP")      /* Territory Jumper Block - see notes */
 	PORT_DIPNAME( 0x0f, 0x02, DEF_STR( Region ) )
 	PORT_DIPSETTING(    0x02, "Europe (Nova Apparate license)" )
@@ -1730,6 +1802,7 @@ static INPUT_PORTS_START( vimanan )
 //  PORT_DIPSETTING(    0x0c, "???" )
 //  PORT_DIPSETTING(    0x0d, "???" )
 //  PORT_DIPSETTING(    0x0e, "???" )
+	PORT_BIT( 0xf0, IP_ACTIVE_HIGH, IPT_UNKNOWN )
 
 	/* P1 : 0x44000b.b */
 	/* P2 : 0x44000d.b */
@@ -1737,7 +1810,7 @@ static INPUT_PORTS_START( vimanan )
 	/* VBLANK : 0x400001.b */
 INPUT_PORTS_END
 
-/* verified from M68000 - coinage based on "test mode" and handled by the MCU simulation */
+/* verified from M68000 */
 static INPUT_PORTS_START( vimanaj )
 	PORT_INCLUDE( vimana )
 
@@ -1745,6 +1818,7 @@ static INPUT_PORTS_START( vimanaj )
 	/* DSWB : 0x44000f.b */
 
 	/* 0x440011.b */
+	/* same as above, this is inverted, handled by vimana_tjump_invert_r */
 	PORT_MODIFY("TJUMP")      /* Territory Jumper Block - see notes */
 	PORT_DIPNAME( 0x0f, 0x00, DEF_STR( Region ) )
 //  PORT_DIPSETTING(    0x02, DEF_STR( Europe ) )
@@ -2015,8 +2089,10 @@ static MACHINE_CONFIG_START( samesame, toaplan1_state )
 	MCFG_CPU_VBLANK_INT_DRIVER("screen", toaplan1_state,  toaplan1_interrupt)
 
 	MCFG_CPU_ADD("audiocpu", Z180, XTAL_28MHz/8)    /* HD647180XOFS6 CPU */
-	MCFG_CPU_PROGRAM_MAP(hd647180_mem_map)
-	MCFG_DEVICE_DISABLE()       /* Internal code is not dumped */
+	MCFG_CPU_PROGRAM_MAP(samesame_hd647180_mem_map)
+	MCFG_CPU_IO_MAP(samesame_hd647180_io_map)
+
+	MCFG_QUANTUM_PERFECT_CPU("maincpu")
 
 	MCFG_MACHINE_RESET_OVERRIDE(toaplan1_state,zerowing)
 
@@ -2127,8 +2203,10 @@ static MACHINE_CONFIG_START( vimana, toaplan1_state )
 	MCFG_CPU_VBLANK_INT_DRIVER("screen", toaplan1_state,  toaplan1_interrupt)
 
 	MCFG_CPU_ADD("audiocpu", Z180, XTAL_28MHz/8)    /* HD647180XOFS6 CPU */
-	MCFG_CPU_PROGRAM_MAP(hd647180_mem_map)
-	MCFG_DEVICE_DISABLE()       /* Internal code is not dumped */
+	MCFG_CPU_PROGRAM_MAP(vimana_hd647180_mem_map)
+	MCFG_CPU_IO_MAP(vimana_hd647180_io_map)
+
+	MCFG_QUANTUM_TIME(attotime::from_hz(600)) // GUESSED
 
 	MCFG_MACHINE_RESET_OVERRIDE(toaplan1_state,vimana)
 
@@ -2553,8 +2631,7 @@ ROM_START( samesame )
 	ROM_LOAD16_BYTE( "o17_12.7l",  0x040001, 0x20000, CRC(ef698811) SHA1(4c729704eba0bf469599c79009327e4fa5dc540b) )
 
 	ROM_REGION( 0x8000, "audiocpu", 0 )    /* Sound HD647180 code */
-	/* sound CPU is a HD647180 (Z180) with internal ROM - not yet supported */
-	ROM_LOAD( "hd647180.017",  0x00000, 0x08000, NO_DUMP )
+	ROM_LOAD( "hd647180.017",  0x00000, 0x08000, CRC(43523032) SHA1(1b94003a00e7bf6bdf1b1b946f42ff5d04629949) )
 
 	ROM_REGION( 0x80000, "gfx1", 0 )
 	ROM_LOAD16_BYTE( "o17_05.12j",  0x00000, 0x20000, CRC(565315f8) SHA1(6b1c5ef52359483228b329c89c2e1174e3fbf017) )
@@ -2581,8 +2658,34 @@ ROM_START( samesame2 )
 	ROM_LOAD16_BYTE( "o17_12ii.7l", 0x040001, 0x20000, CRC(6adb6eb5) SHA1(9b6e63aa50d271c2bb0b4cf822fc6f3684f10230) )
 
 	ROM_REGION( 0x8000, "audiocpu", 0 )    /* Sound HD647180 code */
-	/* sound CPU is a HD647180 (Z180) with internal ROM - not yet supported */
-	ROM_LOAD( "hd647180.017",  0x00000, 0x08000, NO_DUMP )
+	ROM_LOAD( "hd647180.017",  0x00000, 0x08000, CRC(43523032) SHA1(1b94003a00e7bf6bdf1b1b946f42ff5d04629949) )
+
+	ROM_REGION( 0x80000, "gfx1", 0 )
+	ROM_LOAD16_BYTE( "o17_05.12j",  0x00000, 0x20000, CRC(565315f8) SHA1(6b1c5ef52359483228b329c89c2e1174e3fbf017) )
+	ROM_LOAD16_BYTE( "o17_06.13j",  0x00001, 0x20000, CRC(95262d4c) SHA1(16f3aabecb1c87ce7eadf4f0ff61b29a4c017614) )
+	ROM_LOAD16_BYTE( "o17_07.12l",  0x40000, 0x20000, CRC(4c4b735c) SHA1(812c3bf46bd7764b2bb812bd2b9eb0331ed257ae) )
+	ROM_LOAD16_BYTE( "o17_08.13l",  0x40001, 0x20000, CRC(95c6586c) SHA1(ff87901f79d80f73ad09664b0c0d892898570616) )
+
+	ROM_REGION( 0x80000, "gfx2", 0 )
+	ROM_LOAD16_BYTE( "o17_01.1d",  0x00000, 0x20000, CRC(ea12e491) SHA1(02190722b7c5383471e0af9596be7039a5367240) )
+	ROM_LOAD16_BYTE( "o17_02.3d",  0x00001, 0x20000, CRC(32a13a9f) SHA1(1446acdfd21cd41f3d97aaf30f498c0c5d890605) )
+	ROM_LOAD16_BYTE( "o17_03.5d",  0x40000, 0x20000, CRC(68723dc9) SHA1(4f1b7aa2469c955e03737b611a7d2524f1e4f61e) )
+	ROM_LOAD16_BYTE( "o17_04.7d",  0x40001, 0x20000, CRC(fe0ecb13) SHA1(634a49262b9c092c25f11b14c6757fe94ea9eddc) )
+
+	ROM_REGION( 0x40, "proms", 0 )      /* nibble bproms, lo/hi order to be determined */
+	ROM_LOAD( "prom14.25b",  0x00, 0x20, CRC(bc88cced) SHA1(5055362710c0f58823c05fb4c0e0eec638b91e3d) ) /* sprite attribute (flip/position) ?? */
+	ROM_LOAD( "prom15.20c",  0x20, 0x20, CRC(a1e17492) SHA1(9ddec4c97f2d541f69f3c32c47aaa21fd9699ae2) ) /* ??? */
+ROM_END
+
+ROM_START( samesamenh ) /* this hack has been used on various PCBs */
+	ROM_REGION( 0x080000, "maincpu", 0 )    /* Main 68K code */
+	ROM_LOAD16_BYTE( "o17_09_nv.8j",  0x000000, 0x08000, CRC(f60af2f9) SHA1(ce41efd5ca4f4adc8bf1976f61a8a8d357fb234a) )
+	ROM_LOAD16_BYTE( "o17_10_nv.8l",  0x000001, 0x08000, CRC(023bcb95) SHA1(69a051fb223e6cacaf1cda8bf5430933d24fb8a7) )
+	ROM_LOAD16_BYTE( "o17_11.7j",  0x040000, 0x20000, CRC(be07d101) SHA1(1eda14ba24532b565d6ad57490b73ff312f98b53) )
+	ROM_LOAD16_BYTE( "o17_12.7l",  0x040001, 0x20000, CRC(ef698811) SHA1(4c729704eba0bf469599c79009327e4fa5dc540b) )
+
+	ROM_REGION( 0x8000, "audiocpu", 0 )    /* Sound HD647180 code */
+	ROM_LOAD( "hd647180.017",  0x00000, 0x08000, CRC(43523032) SHA1(1b94003a00e7bf6bdf1b1b946f42ff5d04629949) )
 
 	ROM_REGION( 0x80000, "gfx1", 0 )
 	ROM_LOAD16_BYTE( "o17_05.12j",  0x00000, 0x20000, CRC(565315f8) SHA1(6b1c5ef52359483228b329c89c2e1174e3fbf017) )
@@ -2662,8 +2765,7 @@ ROM_START( fireshrk )
 	ROM_LOAD16_BYTE( "o17_12ii.7l", 0x040001, 0x20000, CRC(6adb6eb5) SHA1(9b6e63aa50d271c2bb0b4cf822fc6f3684f10230) )
 
 	ROM_REGION( 0x8000, "audiocpu", 0 )    /* Sound HD647180 code */
-	/* sound CPU is a HD647180 (Z180) with internal ROM - not yet supported */
-	ROM_LOAD( "hd647180.017",  0x00000, 0x08000, NO_DUMP )
+	ROM_LOAD( "hd647180.017",  0x00000, 0x08000, CRC(43523032) SHA1(1b94003a00e7bf6bdf1b1b946f42ff5d04629949) )
 
 	ROM_REGION( 0x80000, "gfx1", 0 )
 	ROM_LOAD16_BYTE( "o17_05.12j",  0x00000, 0x20000, CRC(565315f8) SHA1(6b1c5ef52359483228b329c89c2e1174e3fbf017) )
@@ -2690,8 +2792,7 @@ ROM_START( fireshrka )
 	ROM_LOAD16_BYTE( "o17_12ii.7l", 0x040001, 0x20000, CRC(6adb6eb5) SHA1(9b6e63aa50d271c2bb0b4cf822fc6f3684f10230) )
 
 	ROM_REGION( 0x8000, "audiocpu", 0 )    /* Sound HD647180 code */
-	/* sound CPU is a HD647180 (Z180) with internal ROM - not yet supported */
-	ROM_LOAD( "hd647180.017",  0x00000, 0x08000, NO_DUMP )
+	ROM_LOAD( "hd647180.017",  0x00000, 0x08000, CRC(43523032) SHA1(1b94003a00e7bf6bdf1b1b946f42ff5d04629949) )
 
 	ROM_REGION( 0x80000, "gfx1", 0 )
 	ROM_LOAD16_BYTE( "o17_05.12j",  0x00000, 0x20000, CRC(565315f8) SHA1(6b1c5ef52359483228b329c89c2e1174e3fbf017) )
@@ -2718,8 +2819,7 @@ ROM_START( fireshrkd )
 	ROM_LOAD16_BYTE( "o17_12ii.7l", 0x040001, 0x20000, CRC(6adb6eb5) SHA1(9b6e63aa50d271c2bb0b4cf822fc6f3684f10230) )
 
 	ROM_REGION( 0x8000, "audiocpu", 0 )    /* Sound HD647180 code */
-	/* sound CPU is a HD647180 (Z180) with internal ROM - not yet supported */
-	ROM_LOAD( "hd647180.017",  0x00000, 0x08000, NO_DUMP )
+	ROM_LOAD( "hd647180.017",  0x00000, 0x08000, CRC(43523032) SHA1(1b94003a00e7bf6bdf1b1b946f42ff5d04629949) )
 
 	ROM_REGION( 0x80000, "gfx1", 0 )
 	ROM_LOAD16_BYTE( "o17_05.12j",  0x00000, 0x20000, CRC(565315f8) SHA1(6b1c5ef52359483228b329c89c2e1174e3fbf017) )
@@ -2746,8 +2846,7 @@ ROM_START( fireshrkdh )
 	ROM_LOAD16_BYTE( "o17_12ii.7l", 0x040001, 0x20000, CRC(6adb6eb5) SHA1(9b6e63aa50d271c2bb0b4cf822fc6f3684f10230) )
 
 	ROM_REGION( 0x8000, "audiocpu", 0 )    /* Sound HD647180 code */
-	/* sound CPU is a HD647180 (Z180) with internal ROM - not yet supported */
-	ROM_LOAD( "hd647180.017",  0x00000, 0x08000, NO_DUMP )
+	ROM_LOAD( "hd647180.017",  0x00000, 0x08000, CRC(43523032) SHA1(1b94003a00e7bf6bdf1b1b946f42ff5d04629949) )
 
 	ROM_REGION( 0x80000, "gfx1", 0 )
 	ROM_LOAD16_BYTE( "o17_05.12j",  0x00000, 0x20000, CRC(565315f8) SHA1(6b1c5ef52359483228b329c89c2e1174e3fbf017) )
@@ -2929,8 +3028,8 @@ ROM_START( vimana )         /* From board serial number 1547.04 (July '94) */
 	ROM_LOAD16_BYTE( "tp019-8a.bin",  0x000001, 0x20000, CRC(03ba27e8) SHA1(edb5fe741d2a6a7fe5cde9a82317ea1e9447cf73) )
 
 	ROM_REGION( 0x8000, "audiocpu", 0 )    /* Sound HD647180 code */
-	/* sound CPU is a HD647180 (Z180) with internal ROM - not yet supported */
-	ROM_LOAD( "hd647180.019",  0x00000, 0x08000, NO_DUMP )
+	/* sound CPU is a HD647180 (Z180) with internal ROM */
+	ROM_LOAD( "hd647180.019", 0x00000, 0x08000, CRC(41a97ebe) SHA1(9b377086e4d9b8de6e3c8c7d2dd099b80ab88934) )
 
 	ROM_REGION( 0x80000, "gfx1", 0 )
 	ROM_LOAD16_BYTE( "vim6.bin",  0x00000, 0x20000, CRC(2886878d) SHA1(f44933d87bbcd3bd58f46e0f0f89b05c409b713b) )
@@ -2953,8 +3052,8 @@ ROM_START( vimanan )
 	ROM_LOAD16_BYTE( "tp019-08.rom",  0x000001, 0x20000, CRC(6cd2dc3c) SHA1(029d974eb938c5e2fbe7575f0dda342b4b12b731) )
 
 	ROM_REGION( 0x8000, "audiocpu", 0 )    /* Sound HD647180 code */
-	/* sound CPU is a HD647180 (Z180) with internal ROM - not yet supported */
-	ROM_LOAD( "hd647180.019",  0x00000, 0x08000, NO_DUMP )
+	/* sound CPU is a HD647180 (Z180) with internal ROM */
+	ROM_LOAD( "hd647180.019", 0x00000, 0x08000, CRC(41a97ebe) SHA1(9b377086e4d9b8de6e3c8c7d2dd099b80ab88934) )
 
 	ROM_REGION( 0x80000, "gfx1", 0 )
 	ROM_LOAD16_BYTE( "vim6.bin",  0x00000, 0x20000, CRC(2886878d) SHA1(f44933d87bbcd3bd58f46e0f0f89b05c409b713b) )
@@ -2977,8 +3076,8 @@ ROM_START( vimanaj )
 	ROM_LOAD16_BYTE( "vim08.bin",  0x000001, 0x20000, CRC(e45b7def) SHA1(6b92a91d64581954da8ecdbeb5fed79bcc9c5217) )
 
 	ROM_REGION( 0x8000, "audiocpu", 0 )    /* Sound HD647180 code */
-	/* sound CPU is a HD647180 (Z180) with internal ROM - not yet supported */
-	ROM_LOAD( "hd647180.019",  0x00000, 0x08000, NO_DUMP )
+	/* sound CPU is a HD647180 (Z180) with internal ROM */
+	ROM_LOAD( "hd647180.019", 0x00000, 0x08000, CRC(41a97ebe) SHA1(9b377086e4d9b8de6e3c8c7d2dd099b80ab88934) )
 
 	ROM_REGION( 0x80000, "gfx1", 0 )
 	ROM_LOAD16_BYTE( "vim6.bin",  0x00000, 0x20000, CRC(2886878d) SHA1(f44933d87bbcd3bd58f46e0f0f89b05c409b713b) )
@@ -3007,40 +3106,45 @@ DRIVER_INIT_MEMBER(toaplan1_state,demonwld)
 	demonwld_driver_savestate();
 }
 
-DRIVER_INIT_MEMBER(toaplan1_state,vimana)
-{
-	toaplan1_driver_savestate();
-	vimana_driver_savestate();
-}
+
 
 
 
 GAME( 1988, rallybik,   0,        rallybik, rallybik,  toaplan1_state, toaplan1, ROT270, "Toaplan / Taito Corporation", "Rally Bike / Dash Yarou", 0 )
+
 GAME( 1988, truxton,    0,        truxton,  truxton,   toaplan1_state, toaplan1, ROT270, "Toaplan / Taito Corporation", "Truxton / Tatsujin", 0 )
-GAME( 1989, hellfire,   0,        hellfire, hellfire,  toaplan1_state, toaplan1, ROT0,   "Toaplan (Taito license)", "Hellfire (2P set)", 0 )
-GAME( 1989, hellfire1,  hellfire, hellfire, hellfire1, toaplan1_state, toaplan1, ROT0,   "Toaplan (Taito license)", "Hellfire (1P set)", 0 )
-GAME( 1989, hellfire2a, hellfire, hellfire, hellfire2a,toaplan1_state, toaplan1, ROT0,   "Toaplan (Taito license)", "Hellfire (2P set, older)", 0 )
-GAME( 1989, hellfire1a, hellfire, hellfire, hellfire1a,toaplan1_state, toaplan1, ROT0,   "Toaplan (Taito license)", "Hellfire (1P set, older)", 0 )
-GAME( 1989, zerowing,   0,        zerowing, zerowing2, toaplan1_state, toaplan1, ROT0,   "Toaplan", "Zero Wing (2P set)", 0 )
-GAME( 1989, zerowing1,  zerowing, zerowing, zerowing,  toaplan1_state, toaplan1, ROT0,   "Toaplan", "Zero Wing (1P set)", 0 )
-GAME( 1989, zerowingw,  zerowing, zerowing, zerowing2, toaplan1_state, toaplan1, ROT0,   "Toaplan (Williams license)", "Zero Wing (2P set, Williams license)", 0 )
-GAME( 1990, demonwld,   0,        demonwld, demonwld,  toaplan1_state, demonwld, ROT0,   "Toaplan", "Demon's World / Horror Story (set 1)", 0 )
-GAME( 1989, demonwld1,  demonwld, demonwld, demonwld,  toaplan1_state, demonwld, ROT0,   "Toaplan", "Demon's World / Horror Story (set 2)", 0 )
-GAME( 1989, demonwld2,  demonwld, demonwld, demonwld1, toaplan1_state, demonwld, ROT0,   "Toaplan", "Demon's World / Horror Story (set 3)", 0 )
-GAME( 1989, demonwld3,  demonwld, demonwld, demonwld1, toaplan1_state, demonwld, ROT0,   "Toaplan", "Demon's World / Horror Story (set 4)", 0 )
-GAME( 1989, demonwld4,  demonwld, demonwld, demonwld1, toaplan1_state, demonwld, ROT0,   "Toaplan", "Demon's World / Horror Story (set 5)", 0 )
-GAME( 1990, fireshrk,   0,        samesame, fireshrk,  toaplan1_state, toaplan1, ROT270, "Toaplan", "Fire Shark", MACHINE_NO_SOUND )
-GAME( 1989, fireshrka,  fireshrk, samesame, fireshrka, toaplan1_state, toaplan1, ROT270, "Toaplan", "Fire Shark (earlier)", MACHINE_NO_SOUND )
-GAME( 1990, fireshrkd,  fireshrk, samesame, samesame2, toaplan1_state, toaplan1, ROT270, "Toaplan (Dooyong license)", "Fire Shark (Korea, set 1, easier)", MACHINE_NO_SOUND )
-GAME( 1990, fireshrkdh, fireshrk, samesame, samesame2, toaplan1_state, toaplan1, ROT270, "Toaplan (Dooyong license)", "Fire Shark (Korea, set 2, harder)", MACHINE_NO_SOUND )
-GAME( 1989, samesame,   fireshrk, samesame, samesame,  toaplan1_state, toaplan1, ROT270, "Toaplan", "Same! Same! Same! (1P set)", MACHINE_NO_SOUND )
-GAME( 1989, samesame2,  fireshrk, samesame, samesame2, toaplan1_state, toaplan1, ROT270, "Toaplan", "Same! Same! Same! (2P set)", MACHINE_NO_SOUND )
-GAME( 1990, outzone,    0,        outzone,  outzone,   toaplan1_state, toaplan1, ROT270, "Toaplan", "Out Zone", 0 )
-GAME( 1990, outzoneh,   outzone,  outzone,  outzone,   toaplan1_state, toaplan1, ROT270, "Toaplan", "Out Zone (harder)", 0 )
-GAME( 1990, outzonea,   outzone,  outzone,  outzonea,  toaplan1_state, toaplan1, ROT270, "Toaplan", "Out Zone (old set)", 0 )
-GAME( 1990, outzoneb,   outzone,  outzone,  outzonea,  toaplan1_state, toaplan1, ROT270, "Toaplan", "Out Zone (older set)", 0 )
-GAME( 1990, outzonec,   outzone,  outzone,  outzonec,  toaplan1_state, toaplan1, ROT270, "Toaplan", "Out Zone (oldest set)", MACHINE_IMPERFECT_SOUND ) // prototype?
-GAME( 1990, outzonecv,  outzone,  outzonecv,outzone,   toaplan1_state, toaplan1, ROT270, "Toaplan", "Out Zone (Zero Wing TP-015 PCB conversion)", 0 )
-GAME( 1991, vimana,     0,        vimana,   vimana,    toaplan1_state, vimana,   ROT270, "Toaplan", "Vimana (World, set 1)", MACHINE_NO_SOUND )
-GAME( 1991, vimanan,    vimana,   vimana,   vimanan,   toaplan1_state, vimana,   ROT270, "Toaplan", "Vimana (World, set 2)", MACHINE_NO_SOUND )
-GAME( 1991, vimanaj,    vimana,   vimana,   vimanaj,   toaplan1_state, vimana,   ROT270, "Toaplan", "Vimana (Japan)", MACHINE_NO_SOUND )
+
+GAME( 1989, hellfire,   0,        hellfire, hellfire,  toaplan1_state, toaplan1, ROT0,   "Toaplan (Taito license)",     "Hellfire (2P set)", 0 )
+GAME( 1989, hellfire1,  hellfire, hellfire, hellfire1, toaplan1_state, toaplan1, ROT0,   "Toaplan (Taito license)",     "Hellfire (1P set)", 0 )
+GAME( 1989, hellfire2a, hellfire, hellfire, hellfire2a,toaplan1_state, toaplan1, ROT0,   "Toaplan (Taito license)",     "Hellfire (2P set, older)", 0 )
+GAME( 1989, hellfire1a, hellfire, hellfire, hellfire1a,toaplan1_state, toaplan1, ROT0,   "Toaplan (Taito license)",     "Hellfire (1P set, older)", 0 )
+
+GAME( 1989, zerowing,   0,        zerowing, zerowing2, toaplan1_state, toaplan1, ROT0,   "Toaplan",                     "Zero Wing (2P set)", 0 )
+GAME( 1989, zerowing1,  zerowing, zerowing, zerowing,  toaplan1_state, toaplan1, ROT0,   "Toaplan",                     "Zero Wing (1P set)", 0 )
+GAME( 1989, zerowingw,  zerowing, zerowing, zerowing2, toaplan1_state, toaplan1, ROT0,   "Toaplan (Williams license)",  "Zero Wing (2P set, Williams license)", 0 )
+
+GAME( 1990, demonwld,   0,        demonwld, demonwld,  toaplan1_state, demonwld, ROT0,   "Toaplan",                     "Demon's World / Horror Story (set 1)", 0 )
+GAME( 1989, demonwld1,  demonwld, demonwld, demonwld,  toaplan1_state, demonwld, ROT0,   "Toaplan",                     "Demon's World / Horror Story (set 2)", 0 )
+GAME( 1989, demonwld2,  demonwld, demonwld, demonwld1, toaplan1_state, demonwld, ROT0,   "Toaplan",                     "Demon's World / Horror Story (set 3)", 0 )
+GAME( 1989, demonwld3,  demonwld, demonwld, demonwld1, toaplan1_state, demonwld, ROT0,   "Toaplan",                     "Demon's World / Horror Story (set 4)", 0 )
+GAME( 1989, demonwld4,  demonwld, demonwld, demonwld1, toaplan1_state, demonwld, ROT0,   "Toaplan",                     "Demon's World / Horror Story (set 5)", 0 )
+
+GAME( 1990, fireshrk,   0,        samesame, fireshrk,  toaplan1_state, toaplan1, ROT270, "Toaplan",                     "Fire Shark", 0 )
+GAME( 1989, fireshrka,  fireshrk, samesame, fireshrka, toaplan1_state, toaplan1, ROT270, "Toaplan",                     "Fire Shark (earlier)", 0 )
+GAME( 1990, fireshrkd,  fireshrk, samesame, samesame2, toaplan1_state, toaplan1, ROT270, "Toaplan (Dooyong license)",   "Fire Shark (Korea, set 1, easier)", 0 )
+GAME( 1990, fireshrkdh, fireshrk, samesame, samesame2, toaplan1_state, toaplan1, ROT270, "Toaplan (Dooyong license)",   "Fire Shark (Korea, set 2, harder)", 0 )
+GAME( 1989, samesame,   fireshrk, samesame, samesame,  toaplan1_state, toaplan1, ROT270, "Toaplan",                     "Same! Same! Same! (1P set)", 0 )
+GAME( 1989, samesame2,  fireshrk, samesame, samesame2, toaplan1_state, toaplan1, ROT270, "Toaplan",                     "Same! Same! Same! (2P set)", 0 )
+GAME( 2015, samesamenh, fireshrk, samesame, samesame,  toaplan1_state, toaplan1, ROT270, "hack (trap15)",               "Same! Same! Same! (1P set, NEW VER! hack)", 0 )
+
+GAME( 1990, outzone,    0,        outzone,  outzone,   toaplan1_state, toaplan1, ROT270, "Toaplan",                     "Out Zone", 0 )
+GAME( 1990, outzoneh,   outzone,  outzone,  outzone,   toaplan1_state, toaplan1, ROT270, "Toaplan",                     "Out Zone (harder)", 0 )
+GAME( 1990, outzonea,   outzone,  outzone,  outzonea,  toaplan1_state, toaplan1, ROT270, "Toaplan",                     "Out Zone (old set)", 0 )
+GAME( 1990, outzoneb,   outzone,  outzone,  outzonea,  toaplan1_state, toaplan1, ROT270, "Toaplan",                     "Out Zone (older set)", 0 )
+GAME( 1990, outzonec,   outzone,  outzone,  outzonec,  toaplan1_state, toaplan1, ROT270, "Toaplan",                     "Out Zone (oldest set)", MACHINE_IMPERFECT_SOUND ) // prototype?
+GAME( 1990, outzonecv,  outzone,  outzonecv,outzone,   toaplan1_state, toaplan1, ROT270, "Toaplan",                     "Out Zone (Zero Wing TP-015 PCB conversion)", 0 )
+
+// has various licenses / regions depending on jumpers, including Tecmo
+GAME( 1991, vimana,     0,        vimana,   vimana,    toaplan1_state, toaplan1, ROT270, "Toaplan",                    "Vimana (World, set 1)", 0 )
+GAME( 1991, vimanan,    vimana,   vimana,   vimanan,   toaplan1_state, toaplan1, ROT270, "Toaplan",                    "Vimana (World, set 2)", 0 )
+GAME( 1991, vimanaj,    vimana,   vimana,   vimanaj,   toaplan1_state, toaplan1, ROT270, "Toaplan",                    "Vimana (Japan)", 0 )
diff --git a/src/mame/drivers/toaplan2.cpp b/src/mame/drivers/toaplan2.cpp
index 8ef996f..c8316d6 100644
--- a/src/mame/drivers/toaplan2.cpp
+++ b/src/mame/drivers/toaplan2.cpp
@@ -311,7 +311,7 @@ Graphics Custom 208pin QFP:
 
 Game status:
 
-Teki Paki                      Working, but no sound. Missing sound MCU dump. Chip is protected. It's a QFP80 Hitachi HD647180.
+Teki Paki                      Working. MCU type is a Hitachi HD647180.
 Ghox                           Working, but no sound. Missing sound MCU dump. It's a QFP80 Hitachi HD647180.
 Dogyuun                        Working. MCU type is a NEC V25. Chip is a PLCC94 stamped 'TS-002-MACH'.*
 Knuckle Bash                   Working. MCU type is a NEC V25. Chip is a PLCC94 stamped 'TS-004-DASH'.*
@@ -659,9 +659,9 @@ CUSTOM_INPUT_MEMBER(toaplan2_state::c2map_r)
 	// For Teki Paki hardware
 	// bit 4 high signifies secondary CPU is ready
 	// bit 5 is tested low before V-Blank bit ???
-	m_mcu_data = 0xff;
+	//m_mcu_data = 0xff;
 
-	return (m_mcu_data == 0xff) ? 0x01 : 0x00;
+	return (m_cmdavailable) ? 0x00 : 0x01;
 }
 
 
@@ -998,10 +998,11 @@ static ADDRESS_MAP_START( tekipaki_68k_mem, AS_PROGRAM, 16, toaplan2_state )
 	AM_RANGE(0x180040, 0x180041) AM_WRITE(toaplan2_coin_word_w)
 	AM_RANGE(0x180050, 0x180051) AM_READ_PORT("IN1")
 	AM_RANGE(0x180060, 0x180061) AM_READ_PORT("IN2")
-	AM_RANGE(0x180070, 0x180071) AM_WRITE(toaplan2_hd647180_cpu_w)
+	AM_RANGE(0x180070, 0x180071) AM_WRITE(tekipaki_mcu_w)
 ADDRESS_MAP_END
 
 
+
 static ADDRESS_MAP_START( ghox_68k_mem, AS_PROGRAM, 16, toaplan2_state )
 	AM_RANGE(0x000000, 0x03ffff) AM_ROM
 	AM_RANGE(0x040000, 0x040001) AM_READ(ghox_p2_h_analog_r)
@@ -1506,6 +1507,44 @@ static ADDRESS_MAP_START( fixeightbl_oki, AS_0, 8, toaplan2_state )
 ADDRESS_MAP_END
 
 
+
+WRITE16_MEMBER(toaplan2_state::tekipaki_mcu_w)
+{
+	if (ACCESSING_BITS_0_7)
+	{
+		m_mcu_data = data & 0xff;
+		m_cmdavailable = 1;
+	}
+};
+
+READ8_MEMBER(toaplan2_state::tekipaki_soundlatch_r)
+{
+	m_cmdavailable = 0;
+	return m_mcu_data;
+};
+
+READ8_MEMBER(toaplan2_state::tekipaki_cmdavailable_r)
+{
+	if (m_cmdavailable) return 0xff;
+	else return 0x00;
+};
+
+static ADDRESS_MAP_START( hd647180_mem_map, AS_PROGRAM, 8, toaplan2_state )
+	AM_RANGE(0x00000, 0x03fff) AM_ROM   /* Internal 16k byte ROM */
+	AM_RANGE(0x0fe00, 0x0ffff) AM_RAM   /* Internal 512 byte RAM */
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( hd647180_io_map, AS_IO, 8, toaplan2_state )
+	ADDRESS_MAP_GLOBAL_MASK(0xff)
+
+	AM_RANGE(0x60, 0x60) AM_READ(tekipaki_cmdavailable_r)
+	AM_RANGE(0x84, 0x84) AM_READ(tekipaki_soundlatch_r)
+
+	AM_RANGE(0x82, 0x82) AM_DEVREADWRITE("ymsnd", ym3812_device, status_port_r, control_port_w)
+	AM_RANGE(0x83, 0x83) AM_DEVREADWRITE("ymsnd", ym3812_device, read_port_r, write_port_w)
+ADDRESS_MAP_END
+
+
 /*****************************************************************************
     Input Port definitions
     The following commands are available when the Invulnerability dipswitch
@@ -3014,10 +3053,7 @@ static MACHINE_CONFIG_START( tekipaki, toaplan2_state )
 	MCFG_CPU_PROGRAM_MAP(tekipaki_68k_mem)
 	MCFG_CPU_VBLANK_INT_DRIVER("screen", toaplan2_state,  toaplan2_vblank_irq4)
 
-#ifdef USE_HD64x180
-	MCFG_CPU_ADD("audiocpu", Z180, XTAL_10MHz)          /* HD647180 CPU actually */
-	MCFG_CPU_PROGRAM_MAP(hd647180_mem)
-#endif
+
 
 	MCFG_MACHINE_START_OVERRIDE(toaplan2_state,toaplan2)
 	MCFG_MACHINE_RESET_OVERRIDE(toaplan2_state,toaplan2)
@@ -3045,13 +3081,26 @@ static MACHINE_CONFIG_START( tekipaki, toaplan2_state )
 	MCFG_SPEAKER_STANDARD_MONO("mono")
 
 	MCFG_SOUND_ADD("ymsnd", YM3812, XTAL_27MHz/8)
-#ifdef USE_HD64x180
-	MCFG_YM3812_IRQ_HANDLER(INPUTLINE("audiocpu", 0))
-#endif
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
 MACHINE_CONFIG_END
 
 
+
+static MACHINE_CONFIG_DERIVED( tekipaki_mcu, tekipaki )
+
+	MCFG_CPU_ADD("audiocpu", Z180, XTAL_10MHz)          /* HD647180 CPU actually */
+	MCFG_CPU_PROGRAM_MAP(hd647180_mem_map)
+	MCFG_CPU_IO_MAP(hd647180_io_map)
+
+	MCFG_QUANTUM_TIME(attotime::from_hz(600)) // GUESSED
+
+	MCFG_DEVICE_REMOVE("ymsnd")
+
+	MCFG_SOUND_ADD("ymsnd", YM3812, XTAL_27MHz/8)
+	MCFG_YM3812_IRQ_HANDLER(INPUTLINE("audiocpu", 0))
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
+MACHINE_CONFIG_END
+
 static MACHINE_CONFIG_START( ghox, toaplan2_state )
 
 	/* basic machine hardware */
@@ -4002,9 +4051,8 @@ ROM_START( tekipaki )
 	ROM_LOAD16_BYTE( "tp020-1.bin", 0x000000, 0x010000, CRC(d8420bd5) SHA1(30c1ad9e053cd7e79adb42aa428ebee28e144755) )
 	ROM_LOAD16_BYTE( "tp020-2.bin", 0x000001, 0x010000, CRC(7222de8e) SHA1(8352ae23efc24a2e20cc24b6d37cb8fc6b1a730c) )
 
-	ROM_REGION( 0x10000, "audiocpu", 0 )            /* Sound HD647180 code */
-	/* sound CPU is a HD647180 (Z180) with internal ROM - not yet supported */
-	ROM_LOAD( "hd647180.020", 0x00000, 0x08000, NO_DUMP )
+	ROM_REGION( 0x8000, "audiocpu", 0 )    /* Sound HD647180 code */
+	ROM_LOAD( "hd647180.020", 0x00000, 0x08000, CRC(d5157c12) SHA1(b2c6c087bb539456a9e562d0b40f05dde26cacd3) )
 
 	ROM_REGION( 0x100000, "gp9001", 0 )
 	ROM_LOAD( "tp020-4.bin", 0x000000, 0x080000, CRC(3ebbe41e) SHA1(cea196c5f83e1a23d5b538a0db9bbbffa7af5118) )
@@ -4012,6 +4060,7 @@ ROM_START( tekipaki )
 ROM_END
 
 
+
 ROM_START( ghox ) /* Spinner with single axis (up/down) controls */
 	ROM_REGION( 0x040000, "maincpu", 0 )            /* Main 68K code */
 	ROM_LOAD16_BYTE( "tp021-01.u10", 0x000000, 0x020000, CRC(9e56ac67) SHA1(daf241d9e55a6e60fc004ed61f787641595b1e62) )
@@ -5364,7 +5413,7 @@ ROM_END
 // See list at top of file
 
 //  ( YEAR  NAME        PARENT    MACHINE   INPUT     INIT      MONITOR COMPANY    FULLNAME     FLAGS )
-GAME( 1991, tekipaki,   0,        tekipaki, tekipaki, driver_device, 0,        ROT0,   "Toaplan", "Teki Paki", MACHINE_NO_SOUND | MACHINE_SUPPORTS_SAVE )
+GAME( 1991, tekipaki,   0,        tekipaki_mcu, tekipaki, driver_device, 0,        ROT0,   "Toaplan", "Teki Paki", MACHINE_SUPPORTS_SAVE )
 
 GAME( 1991, ghox,       0,        ghox,     ghox, driver_device,     0,        ROT270, "Toaplan", "Ghox (spinner)", MACHINE_NO_SOUND | MACHINE_SUPPORTS_SAVE )
 GAME( 1991, ghoxj,      ghox,     ghox,     ghox, driver_device,     0,        ROT270, "Toaplan", "Ghox (joystick)", MACHINE_NO_SOUND | MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/drivers/tosh1000.cpp b/src/mame/drivers/tosh1000.cpp
new file mode 100644
index 0000000..ee0150a
--- /dev/null
+++ b/src/mame/drivers/tosh1000.cpp
@@ -0,0 +1,136 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+/***************************************************************************
+
+    Toshiba T1000 portable
+
+    80C88 CPU @ 5 MHz [OKI MSM80C88A-10GS-K (56 pin PQFP)]
+    512KB RAM + 16KB video RAM
+    32KB BIOS ROM [Toshiba TC54256AD]
+    256KB MS-DOS 2.11 ROM [Toshiba TC534000]
+    SuperIO chip (Toshiba T7885) = 82C84 + 82C88 + 82C59 + upd765 + 82C53 + 82C37 + 82C55
+    Real Time Clock chip: TC8521
+    Keyboard controller: 80C50
+    RS232C controller: 8250
+
+    NB: dumps of ROM-DOS and CGA chargen are missing.
+
+***************************************************************************/
+
+
+#include "emu.h"
+
+#include "machine/genpc.h"
+#include "bus/isa/isa_cards.h"
+#include "bus/pc_kbd/keyboards.h"
+#include "cpu/i86/i86.h"
+#include "machine/bankdev.h"
+#include "machine/ram.h"
+#include "machine/rp5c01.h"
+#include "softlist.h"
+
+
+#define VERBOSE_DBG 1       /* general debug messages */
+
+#define DBG_LOG(N,M,A) \
+	do { \
+	if(VERBOSE_DBG>=N) \
+		{ \
+			if( M ) \
+				logerror("%11.6f at %s: %-10s",machine().time().as_double(),machine().describe_context(),(char*)M ); \
+			logerror A; \
+		} \
+	} while (0)
+
+
+
+class tosh1000_state : public driver_device
+{
+public:
+	tosh1000_state(const machine_config &mconfig, device_type type, const char *tag)
+		: driver_device(mconfig, type, tag)
+		, m_maincpu(*this, "maincpu")
+		, m_bankdev(*this, "romdos")
+		{ }
+
+	DECLARE_MACHINE_RESET(tosh1000);
+	DECLARE_DRIVER_INIT(tosh1000);
+
+protected:
+	required_device<cpu_device> m_maincpu;
+	optional_device<address_map_bank_device> m_bankdev;
+};
+
+
+DRIVER_INIT_MEMBER( tosh1000_state, tosh1000 )
+{
+}
+
+MACHINE_RESET_MEMBER( tosh1000_state, tosh1000 )
+{
+}
+
+
+static ADDRESS_MAP_START( tosh1000_map, AS_PROGRAM, 8, tosh1000_state )
+	ADDRESS_MAP_UNMAP_HIGH
+	AM_RANGE(0xa0000, 0xaffff) AM_NOP // AM_DEVREADWRITE("romdos", address_map_bank_device, read8, write8)
+	AM_RANGE(0xf0000, 0xfffff) AM_ROM AM_REGION("bios", 0)
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( tosh1000_io, AS_IO, 8, tosh1000_state )
+	ADDRESS_MAP_UNMAP_HIGH
+	AM_RANGE(0x0000, 0x00ff) AM_DEVICE("mb", ibm5160_mb_device, map)
+	AM_RANGE(0x00c8, 0x00c8) AM_NOP // ROM-DOS page select [p. B-15]
+	AM_RANGE(0x00e0, 0x00ef) AM_NOP // ???
+	AM_RANGE(0x02c0, 0x02cf) AM_DEVREADWRITE("rtc", rp5c01_device, read, write)
+ADDRESS_MAP_END
+
+
+static MACHINE_CONFIG_FRAGMENT( cfg_fdc_35 )
+	MCFG_DEVICE_MODIFY("fdc:0")
+	MCFG_SLOT_DEFAULT_OPTION("35dd")
+	MCFG_SLOT_FIXED(true)
+
+	MCFG_DEVICE_REMOVE("fdc:1")
+MACHINE_CONFIG_END
+
+static MACHINE_CONFIG_START( tosh1000, tosh1000_state )
+	MCFG_CPU_ADD("maincpu", I8088, XTAL_5MHz)
+	MCFG_CPU_PROGRAM_MAP(tosh1000_map)
+	MCFG_CPU_IO_MAP(tosh1000_io)
+	MCFG_CPU_IRQ_ACKNOWLEDGE_DEVICE("mb:pic8259", pic8259_device, inta_cb)
+
+	MCFG_MACHINE_RESET_OVERRIDE(tosh1000_state, tosh1000)
+
+	MCFG_IBM5160_MOTHERBOARD_ADD("mb", "maincpu")
+
+	MCFG_DEVICE_ADD("rtc", RP5C01, XTAL_32_768kHz)
+
+	MCFG_ISA8_SLOT_ADD("mb:isa", "isa1", pc_isa8_cards, "cga", false)
+	MCFG_ISA8_SLOT_ADD("mb:isa", "isa2", pc_isa8_cards, "fdc_xt", false)
+	MCFG_SLOT_OPTION_MACHINE_CONFIG("fdc_xt", cfg_fdc_35)
+	MCFG_ISA8_SLOT_ADD("mb:isa", "isa3", pc_isa8_cards, "lpt", false)
+	MCFG_ISA8_SLOT_ADD("mb:isa", "isa4", pc_isa8_cards, "com", false)
+
+//  MCFG_SOFTWARE_LIST_ADD("flop_list","tosh1000")
+
+	MCFG_PC_KBDC_SLOT_ADD("mb:pc_kbdc", "kbd", pc_xt_keyboards, STR_KBD_KEYTRONIC_PC3270)
+
+	MCFG_RAM_ADD(RAM_TAG)
+	MCFG_RAM_DEFAULT_SIZE("512K")
+MACHINE_CONFIG_END
+
+
+ROM_START( tosh1000 )
+	ROM_REGION16_LE(0x20000,"bios", 0)
+	ROM_SYSTEM_BIOS(0, "v410", "V4.10")
+	ROMX_LOAD( "tosh1000bios410.bin", 0x8000, 0x8000, CRC(a854939f) SHA1(0ff532f295a40716f53949a2fd64d02bf76d575a), ROM_BIOS(1))
+
+	/* XXX IBM 1501981(CGA) and 1501985(MDA) Character rom */
+	ROM_REGION(0x2000,"gfx1", 0)
+	ROM_LOAD("5788005.u33", 0x00000, 0x2000, CRC(0bf56d70) SHA1(c2a8b10808bf51a3c123ba3eb1e9dd608231916f)) /* "AMI 8412PI // 5788005 // (C) IBM CORP. 1981 // KOREA" */
+ROM_END
+
+
+/*     YEAR     ROM NAME    PARENT      COMPAT  MACHINE     INPUT                       INIT        COMPANY     FULLNAME */
+COMP ( 1987,    tosh1000,   ibm5150,    0,      tosh1000,   0,        tosh1000_state,   tosh1000,   "Toshiba",  "Toshiba T1000", MACHINE_IS_SKELETON)
diff --git a/src/mame/drivers/triforce.cpp b/src/mame/drivers/triforce.cpp
index 58344e8..b71dc13 100644
--- a/src/mame/drivers/triforce.cpp
+++ b/src/mame/drivers/triforce.cpp
@@ -70,23 +70,23 @@ Games on this system include....
 | | 2004 | Virtua Striker 4 (Export)                                       | Sega                                | GDROM | GDT-0014       |              |               |
 |*| 2004 | Virtua Striker 4 (Export)                                       | Sega                                | GDROM | GDT-0015       | 317-0393-EXP |               |
 | | 2004 | Virtua Striker 4 (Export)                                       | Sega                                | CF    | MDA-G0016      | 317-0393-EXP |               |
-| | 2004 | The Key Of Avalon 2: Eutaxy Commandment (server)                | Sega / Hitmaker                     | GDROM | GDT-0016       |              |               |
-| | 2004 | The Key Of Avalon 2: Eutaxy Commandment (client)                | Sega / Hitmaker                     | GDROM | GDT-0017       |              |               |
-| | 2004 | The Key Of Avalon 2: Eutaxy Commandment (client) (Rev A)        | Sega / Hitmaker                     | GDROM | GDT-0017A      |              |               |
-|*| 2004 | The Key Of Avalon 2: Eutaxy Commandment (client) (Rev B)        | Sega / Hitmaker                     | GDROM | GDT-0017B      |              |               |
+| | 2004 | The Key Of Avalon 2: Eutaxy Commandment (server)                | Sega / Hitmaker                     | GDROM | GDT-0016       | 317-0403-JPN | 253-5508-0403J|
+| | 2004 | The Key Of Avalon 2: Eutaxy Commandment (client)                | Sega / Hitmaker                     | GDROM | GDT-0017       | 317-0403-JPN | 253-5508-0403J|
+| | 2004 | The Key Of Avalon 2: Eutaxy Commandment (client) (Rev A)        | Sega / Hitmaker                     | GDROM | GDT-0017A      | 317-0403-JPN | 253-5508-0403J|
+|*| 2004 | The Key Of Avalon 2: Eutaxy Commandment (client) (Rev B)        | Sega / Hitmaker                     | GDROM | GDT-0017B      | 317-0403-JPN | 253-5508-0403J|
 | | 2004 | F-Zero AX - Monster Ride Cycraft Edition                        | Sega / Amusement Vision / Nintendo  | GDROM |                |              |               |
 | | 2005 | Donkey Kong Jungle Fever                                        | Namco / Nintendo                    | Cart  |                |              |               |
 |*| 2005 | Mario Kart Arcade GP (Japan, MKA1 Ver.A1)                       | Namco / Nintendo                    | Cart  | 837-14343-4T1  |!317-5109-COM | 253-5509-5109 |
-| | 2005 | The Key Of Avalon 2.5: War of the Key (server)                  | Sega / Hitmaker                     | GDROM | GDT-0018       |              |               |
-| | 2005 | The Key Of Avalon 2.5: War of the Key (server) (Rev A)          | Sega / Hitmaker                     | GDROM | GDT-0018A      |              |               |
-|*| 2005 | The Key Of Avalon 2.5: War of the Key (server) (Rev B)          | Sega / Hitmaker                     | GDROM | GDT-0018B      |              |               |
-| | 2005 | The Key Of Avalon 2.5: War of the Key (client)                  | Sega / Hitmaker                     | GDROM | GDT-0019       |              |               |
-| | 2005 | The Key Of Avalon 2.5: War of the Key (client) (Rev A)          | Sega / Hitmaker                     | GDROM | GDT-0019A      |              |               |
-|*| 2005 | The Key Of Avalon 2.5: War of the Key (client) (Rev B)          | Sega / Hitmaker                     | GDROM | GDT-0019B      |              |               |
-| | 2006 | Virtua Striker 4 Ver.2006 (Japan)                               | Sega                                | GDROM | GDT-0020       |              |               |
-| | 2006 | Virtua Striker 4 Ver.2006 (Japan) (Rev A)                       | Sega                                | GDROM | GDT-0020A      |              |               |
-| | 2006 | Virtua Striker 4 Ver.2006 (Japan) (Rev B)                       | Sega                                | GDROM | GDT-0020B      |              |               |
-| | 2006 | Virtua Striker 4 Ver.2006 (Japan) (Rev C)                       | Sega                                | GDROM | GDT-0020C      |              |               |
+| | 2005 | The Key Of Avalon 2.5: War of the Key (server)                  | Sega / Hitmaker                     | GDROM | GDT-0018       | 317-0403-JPN | 253-5508-0403J|
+| | 2005 | The Key Of Avalon 2.5: War of the Key (server) (Rev A)          | Sega / Hitmaker                     | GDROM | GDT-0018A      | 317-0403-JPN | 253-5508-0403J|
+|*| 2005 | The Key Of Avalon 2.5: War of the Key (server) (Rev B)          | Sega / Hitmaker                     | GDROM | GDT-0018B      | 317-0403-JPN | 253-5508-0403J|
+| | 2005 | The Key Of Avalon 2.5: War of the Key (client)                  | Sega / Hitmaker                     | GDROM | GDT-0019       | 317-0403-JPN | 253-5508-0403J|
+| | 2005 | The Key Of Avalon 2.5: War of the Key (client) (Rev A)          | Sega / Hitmaker                     | GDROM | GDT-0019A      | 317-0403-JPN | 253-5508-0403J|
+|*| 2005 | The Key Of Avalon 2.5: War of the Key (client) (Rev B)          | Sega / Hitmaker                     | GDROM | GDT-0019B      | 317-0403-JPN | 253-5508-0403J|
+| | 2006 | Virtua Striker 4 Ver.2006 (Japan)                               | Sega                                | GDROM | GDT-0020       | 317-0432-JPN | 253-5508-0432J|
+| | 2006 | Virtua Striker 4 Ver.2006 (Japan) (Rev A)                       | Sega                                | GDROM | GDT-0020A      | 317-0432-JPN | 253-5508-0432J|
+| | 2006 | Virtua Striker 4 Ver.2006 (Japan) (Rev B)                       | Sega                                | GDROM | GDT-0020B      | 317-0432-JPN | 253-5508-0432J|
+| | 2006 | Virtua Striker 4 Ver.2006 (Japan) (Rev C)                       | Sega                                | GDROM | GDT-0020C      | 317-0432-JPN | 253-5508-0432J|
 |*| 2006 | Virtua Striker 4 Ver.2006 (Japan) (Rev D)                       | Sega                                | GDROM | GDT-0020D      | 317-0432-JPN | 253-5508-0432J|
 |*| 2006 | Virtua Striker 4 Ver.2006 (Export)                              | Sega                                | GDROM | GDT-0021       | 317-0433-EXP | 253-5508-0433E|
 | | 2006 | Virtua Striker 4 Ver.2006 (Export)                              | Sega                                | CF    | MDA-G00??      | 317-0433-EXP | 253-5508-0433E|
@@ -915,7 +915,7 @@ ROM_START( avalon20 )
 	DISK_IMAGE_READONLY( "gdt-0017b", 0, BAD_DUMP SHA1(e2dd32c322ffcaf38b82275d2721b71bb3dfc1f2) )
 
 	ROM_REGION( 0x50, "pic", ROMREGION_ERASE)
-	ROM_LOAD("avalon2x.data", 0x00, 0x50, CRC(c5071ada) SHA1(70018180b917beec1b2c272f9125fa43fd1a7b00) )
+	ROM_LOAD("317-0403-jpn.data", 0x00, 0x50, CRC(c5071ada) SHA1(70018180b917beec1b2c272f9125fa43fd1a7b00) )
 ROM_END
 
 ROM_START( avalns25 )
@@ -925,7 +925,7 @@ ROM_START( avalns25 )
 	DISK_IMAGE_READONLY( "gdt-0018b", 0, SHA1(4cd10813e66b72021ca344886638025f979d40c0) )
 
 	ROM_REGION( 0x50, "pic", ROMREGION_ERASE)
-	ROM_LOAD("avalon2x.data", 0x00, 0x50, CRC(c5071ada) SHA1(70018180b917beec1b2c272f9125fa43fd1a7b00) )
+	ROM_LOAD("317-0403-jpn.data", 0x00, 0x50, CRC(c5071ada) SHA1(70018180b917beec1b2c272f9125fa43fd1a7b00) )
 ROM_END
 
 ROM_START( avalnc25 )
@@ -935,7 +935,7 @@ ROM_START( avalnc25 )
 	DISK_IMAGE_READONLY( "gdt-0019b", 0, SHA1(7f978ec998a86ed9c36a495bfa72073c6d2bbe31) )
 
 	ROM_REGION( 0x50, "pic", ROMREGION_ERASE)
-	ROM_LOAD("avalon2x.data", 0x00, 0x50, CRC(c5071ada) SHA1(70018180b917beec1b2c272f9125fa43fd1a7b00) )
+	ROM_LOAD("317-0403-jpn.data", 0x00, 0x50, CRC(c5071ada) SHA1(70018180b917beec1b2c272f9125fa43fd1a7b00) )
 ROM_END
 
 ROM_START( vs42006 )
@@ -945,7 +945,7 @@ ROM_START( vs42006 )
 	DISK_IMAGE_READONLY( "gdt-0020d", 0, BAD_DUMP SHA1(db256d094b9754d452d7a2b8a370699d21141c1f) )
 
 	ROM_REGION( 0x50, "pic", ROMREGION_ERASE)
-	ROM_LOAD("gdt-0020.data", 0x00, 0x50, CRC(e3d13191) SHA1(4255c09aad06eb38c16bdec881897404a3a68b37) )
+	ROM_LOAD("317-0432-jpn.data", 0x00, 0x50, CRC(e3d13191) SHA1(4255c09aad06eb38c16bdec881897404a3a68b37) )
 ROM_END
 
 /*
diff --git a/src/mame/drivers/v6809.cpp b/src/mame/drivers/v6809.cpp
index 9033a4c..abdfaba 100644
--- a/src/mame/drivers/v6809.cpp
+++ b/src/mame/drivers/v6809.cpp
@@ -339,8 +339,7 @@ static MACHINE_CONFIG_START( v6809, v6809_state )
 	MCFG_PIA_IRQA_HANDLER(INPUTLINE("maincpu", M6809_IRQ_LINE))
 	MCFG_PIA_IRQB_HANDLER(INPUTLINE("maincpu", M6809_IRQ_LINE))
 
-	MCFG_DEVICE_ADD("ptm", PTM6840, 0)
-	MCFG_PTM6840_INTERNAL_CLOCK(XTAL_16MHz / 4)
+	MCFG_DEVICE_ADD("ptm", PTM6840, XTAL_16MHz / 4)
 	MCFG_PTM6840_EXTERNAL_CLOCKS(4000000/14, 4000000/14, 4000000/14/8)
 	MCFG_PTM6840_OUT1_CB(WRITELINE(v6809_state, speaker_w))
 	MCFG_PTM6840_OUT2_CB(WRITELINE(v6809_state, speaker_en_w))
diff --git a/src/mame/drivers/vaportra.cpp b/src/mame/drivers/vaportra.cpp
index 469a51b..a62d3f8 100644
--- a/src/mame/drivers/vaportra.cpp
+++ b/src/mame/drivers/vaportra.cpp
@@ -1,11 +1,17 @@
 // license:BSD-3-Clause
 // copyright-holders:Bryan McPhail
+
 /***************************************************************************
 
   Vapor Trail (World version)  (c) 1989 Data East Corporation
   Vapor Trail (USA version)    (c) 1989 Data East USA
   Kuhga (Japanese version)     (c) 1989 Data East Corporation
 
+  Notes:
+  -----
+  - If you activate the service mode dip switch during the gameplay, it acts like invicibility
+    either for player 1 and player 2. It works for all sets.
+
   Emulation by Bryan McPhail, mish at tendril.co.uk
   added pal & prom-maps - Highwayman.
 ***************************************************************************/
@@ -28,6 +34,20 @@ WRITE16_MEMBER(vaportra_state::vaportra_sound_w)
 	m_audiocpu->set_input_line(0, ASSERT_LINE);
 }
 
+READ16_MEMBER(vaportra_state::irq6_ack_r)
+{
+	if (ACCESSING_BITS_0_7)
+		m_maincpu->set_input_line (6, CLEAR_LINE);
+
+	return (0);
+}
+
+WRITE16_MEMBER(vaportra_state::irq6_ack_w)
+{
+	if (ACCESSING_BITS_0_7)
+		m_maincpu->set_input_line (6, CLEAR_LINE);
+}
+
 READ16_MEMBER(vaportra_state::vaportra_control_r)
 {
 	switch (offset << 1)
@@ -59,9 +79,9 @@ static ADDRESS_MAP_START( main_map, AS_PROGRAM, 16, vaportra_state )
 	AM_RANGE(0x2c0000, 0x2c000f) AM_DEVWRITE("tilegen1", deco16ic_device, pf_control_w)
 	AM_RANGE(0x300000, 0x3009ff) AM_RAM_WRITE(vaportra_palette_24bit_rg_w) AM_SHARE("paletteram")
 	AM_RANGE(0x304000, 0x3049ff) AM_RAM_WRITE(vaportra_palette_24bit_b_w) AM_SHARE("paletteram2")
-	AM_RANGE(0x308000, 0x308001) AM_NOP
+	AM_RANGE(0x308000, 0x308001) AM_READWRITE(irq6_ack_r, irq6_ack_w)
 	AM_RANGE(0x30c000, 0x30c001) AM_DEVWRITE("spriteram", buffered_spriteram16_device, write)
-	AM_RANGE(0xff8000, 0xff87ff) AM_RAM AM_SHARE("spriteram")
+	AM_RANGE(0x318000, 0x3187ff) AM_MIRROR(0xce0000) AM_RAM AM_SHARE("spriteram")
 	AM_RANGE(0xffc000, 0xffffff) AM_RAM
 ADDRESS_MAP_END
 
@@ -110,7 +130,7 @@ static INPUT_PORTS_START( vaportra )
 	PORT_START("COINS")
 	PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_COIN1 )
 	PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_COIN2 )
-	PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_COIN3 )
+	PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_SERVICE1 )
 	PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_VBLANK("screen")
 	PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_UNKNOWN )
 	PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_UNKNOWN )
@@ -219,7 +239,7 @@ static MACHINE_CONFIG_START( vaportra, vaportra_state )
 	/* basic machine hardware */
 	MCFG_CPU_ADD("maincpu", M68000,XTAL_24MHz/2) /* Custom chip 59 */
 	MCFG_CPU_PROGRAM_MAP(main_map)
-	MCFG_CPU_VBLANK_INT_DRIVER("screen", vaportra_state,  irq6_line_hold)
+	MCFG_CPU_VBLANK_INT_DRIVER("screen", vaportra_state, irq6_line_assert)
 
 	MCFG_CPU_ADD("audiocpu", H6280, XTAL_24MHz/4) /* Custom chip 45; Audio section crystal is 32.220 MHz but CPU clock is confirmed as coming from the 24MHz crystal (6Mhz exactly on the CPU) */
 	MCFG_CPU_PROGRAM_MAP(sound_map)
@@ -838,15 +858,14 @@ C3D54*
 DRIVER_INIT_MEMBER(vaportra_state,vaportra)
 {
 	uint8_t *RAM = memregion("maincpu")->base();
-	int i;
 
-	for (i = 0x00000; i < 0x80000; i++)
+	for (int i = 0x00000; i < 0x80000; i++)
 		RAM[i] = BITSWAP8(RAM[i],0,6,5,4,3,2,1,7);
 }
 
 /******************************************************************************/
 
-GAME( 1989, vaportra, 0,        vaportra, vaportra, vaportra_state, vaportra, ROT270, "Data East Corporation", "Vapor Trail - Hyper Offence Formation (World revision 1)", MACHINE_SUPPORTS_SAVE )
-GAME( 1989, vaportra3,vaportra, vaportra, vaportra, vaportra_state, vaportra, ROT270, "Data East Corporation", "Vapor Trail - Hyper Offence Formation (World revision 3?)", MACHINE_SUPPORTS_SAVE )
-GAME( 1989, vaportrau,vaportra, vaportra, vaportra, vaportra_state, vaportra, ROT270, "Data East USA", "Vapor Trail - Hyper Offence Formation (US)", MACHINE_SUPPORTS_SAVE )
-GAME( 1989, kuhga,    vaportra, vaportra, vaportra, vaportra_state, vaportra, ROT270, "Data East Corporation", "Kuhga - Operation Code 'Vapor Trail' (Japan revision 3)", MACHINE_SUPPORTS_SAVE )
+GAME( 1989, vaportra,  0,        vaportra, vaportra, vaportra_state, vaportra, ROT270, "Data East Corporation", "Vapor Trail - Hyper Offence Formation (World revision 1)",  MACHINE_SUPPORTS_SAVE )
+GAME( 1989, vaportra3, vaportra, vaportra, vaportra, vaportra_state, vaportra, ROT270, "Data East Corporation", "Vapor Trail - Hyper Offence Formation (World revision 3?)", MACHINE_SUPPORTS_SAVE )
+GAME( 1989, vaportrau, vaportra, vaportra, vaportra, vaportra_state, vaportra, ROT270, "Data East USA",         "Vapor Trail - Hyper Offence Formation (US)",                MACHINE_SUPPORTS_SAVE )
+GAME( 1989, kuhga,     vaportra, vaportra, vaportra, vaportra_state, vaportra, ROT270, "Data East Corporation", "Kuhga - Operation Code 'Vapor Trail' (Japan revision 3)",   MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/drivers/vega.cpp b/src/mame/drivers/vega.cpp
index 144625a..0626200 100644
--- a/src/mame/drivers/vega.cpp
+++ b/src/mame/drivers/vega.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /***************************************************************************
 Vega by Olympia
diff --git a/src/mame/drivers/vegas.cpp b/src/mame/drivers/vegas.cpp
index 893f25d..33e7e4c 100644
--- a/src/mame/drivers/vegas.cpp
+++ b/src/mame/drivers/vegas.cpp
@@ -1244,7 +1244,7 @@ WRITE32_MEMBER( vegas_state::nile_w )
 			break;
 
 		case NREG_UARTTHR:      /* serial port output */
-			if (PRINTF_SERIAL) osd_printf_debug("%c", data & 0xff);
+			if (PRINTF_SERIAL) osd_printf_info("%c", data & 0xff);
 			logit = 0;
 			break;
 		case NREG_UARTIER:      /* serial interrupt enable */
diff --git a/src/mame/drivers/vis.cpp b/src/mame/drivers/vis.cpp
index 27c4f73..bedd268 100644
--- a/src/mame/drivers/vis.cpp
+++ b/src/mame/drivers/vis.cpp
@@ -246,7 +246,8 @@ private:
 	uint8_t m_extreg;
 	uint8_t m_interlace;
 	uint16_t m_wina, m_winb;
-	uint8_t m_shift256, m_dw;
+	uint8_t m_shift256, m_dw, m_8bit_640;
+	uint8_t m_crtc_regs[0x31];
 };
 
 const device_type VIS_VGA = &device_creator<vis_vga_device>;
@@ -277,16 +278,15 @@ void vis_vga_device::recompute_params()
 	int pixel_clock;
 	int xtal = (vga.miscellaneous_output & 0xc) ? XTAL_28_63636MHz : XTAL_25_1748MHz;
 	int divisor = 1; // divisor is 2 for 15/16 bit rgb/yuv modes and 3 for 24bit
-	int interlace = m_interlace ? 2 : 1;
 
 	/* safety check */
 	if(!vga.crtc.horz_disp_end || !vga.crtc.vert_disp_end || !vga.crtc.horz_total || !vga.crtc.vert_total)
 		return;
 
-	rectangle visarea(0, ((vga.crtc.horz_disp_end + 1) / interlace * ((float)(hclock_m)/divisor))-1, 0, vga.crtc.vert_disp_end * interlace);
+	rectangle visarea(0, ((vga.crtc.horz_disp_end + 1) * ((float)(hclock_m)/divisor))-1, 0, vga.crtc.vert_disp_end);
 
-	vblank_period = (vga.crtc.vert_total * interlace + 2);
-	hblank_period = ((vga.crtc.horz_total + 5) / interlace * ((float)(hclock_m)/divisor));
+	vblank_period = (vga.crtc.vert_total + 2);
+	hblank_period = ((vga.crtc.horz_total + 5) * ((float)(hclock_m)/divisor));
 
 	/* TODO: 10b and 11b settings aren't known */
 	pixel_clock = xtal / (((vga.sequencer.data[1]&8) >> 3) + 1);
@@ -294,7 +294,7 @@ void vis_vga_device::recompute_params()
 	refresh  = HZ_TO_ATTOSECONDS(pixel_clock) * (hblank_period) * vblank_period;
 	machine().first_screen()->configure((hblank_period), (vblank_period), visarea, refresh );
 	//popmessage("%d %d\n",vga.crtc.horz_total * 8,vga.crtc.vert_total);
-	m_vblank_timer->adjust( machine().first_screen()->time_until_pos((vga.crtc.vert_blank_start + vga.crtc.vert_blank_end) * interlace) );
+	m_vblank_timer->adjust( machine().first_screen()->time_until_pos((vga.crtc.vert_blank_start + vga.crtc.vert_blank_end)) );
 }
 
 rgb_t vis_vga_device::yuv_to_rgb(int y, int u, int v) const
@@ -315,9 +315,8 @@ void vis_vga_device::vga_vh_yuv8(bitmap_rgb32 &bitmap, const rectangle &cliprect
 	int pos, line, column, col, addr, curr_addr = 0;
 	const uint8_t decode_tbl[] = {0, 1, 2, 3, 4, 5, 6, 9, 12, 17, 22, 29, 38, 50, 66, 91, 128, 165, 190,
 		206, 218, 227, 234, 239, 244, 247, 250, 251, 252, 253, 254, 255};
-	int interlace = m_interlace ? 2 : 1;
 
-	for (addr = vga.crtc.start_addr, line=0; line<(vga.crtc.vert_disp_end+1) * interlace; line+=height, addr+=offset(), curr_addr+=offset())
+	for (addr = vga.crtc.start_addr, line=0; line<(vga.crtc.vert_disp_end+1); line+=height, addr+=offset(), curr_addr+=offset())
 	{
 		for(int yi = 0;yi < height; yi++)
 		{
@@ -326,7 +325,7 @@ void vis_vga_device::vga_vh_yuv8(bitmap_rgb32 &bitmap, const rectangle &cliprect
 				curr_addr = addr;
 			if((line + yi) == (vga.crtc.line_compare & 0x3ff))
 				curr_addr = 0;
-			for (pos=curr_addr, col=0, column=0; column<(vga.crtc.horz_disp_end+1) / interlace; column++, col+=8, pos+=8)
+			for (pos=curr_addr, col=0, column=0; column<(vga.crtc.horz_disp_end+1); column++, col+=8, pos+=8)
 			{
 				if(pos + 0x08 > 0x80000)
 					return;
@@ -388,6 +387,7 @@ void vis_vga_device::device_start()
 	m_isa->install_device(0x03b0, 0x03df, read8_delegate(FUNC(vis_vga_device::vga_r), this), write8_delegate(FUNC(vis_vga_device::vga_w), this));
 	m_isa->install_memory(0x0a0000, 0x0bffff, read8_delegate(FUNC(vis_vga_device::visvgamem_r), this), write8_delegate(FUNC(vis_vga_device::visvgamem_w), this));
 	svga_device::device_start();
+	vga.svga_intf.seq_regcount = 0x2d;
 }
 
 void vis_vga_device::device_reset()
@@ -399,6 +399,7 @@ void vis_vga_device::device_reset()
 	m_interlace = 0;
 	m_shift256 = 0;
 	m_dw = 0;
+	m_8bit_640 = 0;
 }
 
 uint32_t vis_vga_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
@@ -439,28 +440,34 @@ uint32_t vis_vga_device::screen_update(screen_device &screen, bitmap_rgb32 &bitm
 
 READ8_MEMBER(vis_vga_device::visvgamem_r)
 {
-	if(!m_winb)
+	if(!(vga.sequencer.data[0x25] & 0x40))
 		return mem_r(space, offset, mem_mask);
-	return mem_linear_r(space, (offset + (m_winb * 64)) & 0x3ffff, mem_mask);
+	u16 win = (vga.sequencer.data[0x1e] & 0x0f) == 3 ? m_wina : m_winb; // this doesn't seem quite right
+	return mem_linear_r(space, (offset + (win * 64)) & 0x3ffff, mem_mask);
 }
 
 WRITE8_MEMBER(vis_vga_device::visvgamem_w)
 {
-	if(!m_wina)
+	if(!(vga.sequencer.data[0x25] & 0x40))
 		return mem_w(space, offset, data, mem_mask);
 	return mem_linear_w(space, (offset + (m_wina * 64)) & 0x3ffff, data, mem_mask);
 }
 
 READ8_MEMBER(vis_vga_device::vga_r)
 {
-	if(offset == 0x16)
+	switch(offset)
 	{
-		if(m_extcnt == 4)
-		{
-			m_extcnt = 0;
-			return m_extreg;
-		}
-		m_extcnt++;
+		case 0x16:
+			if(m_extcnt == 4)
+			{
+				m_extcnt = 0;
+				return m_extreg;
+			}
+			m_extcnt++;
+			break;
+		case 0x05:
+		case 0x25:
+			return m_crtc_regs[vga.crtc.index];
 	}
 	if(offset < 0x10)
 		return port_03b0_r(space, offset, mem_mask);
@@ -477,6 +484,13 @@ WRITE8_MEMBER(vis_vga_device::vga_w)
 		case 0x15:
 			switch(vga.sequencer.index)
 			{
+				case 0x01:
+					m_8bit_640 = (data & 8) ? 0 : 1;
+					if(m_8bit_640 && (vga.sequencer.data[0x1f] & 0x10))
+						svga.rgb8_en = 1;
+					else
+						svga.rgb8_en = 0;
+					break;
 				case 0x19:
 					m_wina = (m_wina & 0xff00) | data;
 					break;
@@ -494,11 +508,16 @@ WRITE8_MEMBER(vis_vga_device::vga_w)
 					{
 						vga.gc.shift256 = 1;
 						vga.crtc.dw = 1;
+						if(m_8bit_640)
+							svga.rgb8_en = 1;
+						else
+							svga.rgb8_en = 0;
 					}
 					else
 					{
 						vga.gc.shift256 = m_shift256;
 						vga.crtc.dw = m_dw;
+						svga.rgb8_en = 0;
 					}
 					break;
 			}
@@ -516,22 +535,154 @@ WRITE8_MEMBER(vis_vga_device::vga_w)
 			if(vga.gc.index == 0x05)
 			{
 				m_shift256 = data & 0x40 ? 1 : 0;
-				// remove this if it is shown to be unneeded
-				//if(vga.sequencer.data[0x1f] | 0x10)
-					//data |= 0x40;
+				if(vga.sequencer.data[0x1f] & 0x10)
+					data |= 0x40;
 			}
 			break;
 		case 0x05:
 		case 0x25:
+			m_crtc_regs[vga.crtc.index] = data;
 			switch(vga.crtc.index)
 			{
+				case 0x00:
+					if(vga.crtc.protect_enable)
+						return;
+					vga.crtc.horz_total = data / (m_interlace && !(vga.sequencer.data[0x25] & 0x20) ? 2 : 1);
+					recompute_params();
+					return;
+				case 0x01:
+					if(vga.crtc.protect_enable)
+						return;
+					vga.crtc.horz_disp_end = data / (m_interlace && !(vga.sequencer.data[0x25] & 0x20) ? 2 : 1);
+					recompute_params();
+					return;
+				case 0x02:
+					if(vga.crtc.protect_enable)
+						return;
+					vga.crtc.horz_blank_start = data / (m_interlace && !(vga.sequencer.data[0x25] & 0x20) ? 2 : 1);
+					return;
+				case 0x03:
+					if(vga.crtc.protect_enable)
+						return;
+					vga.crtc.horz_blank_end = (m_crtc_regs[0x05] & 0x80) >> 2;
+					vga.crtc.horz_blank_end |= data & 0x1f;
+					vga.crtc.horz_blank_end /= (m_interlace && !(vga.sequencer.data[0x25] & 0x20) ? 2 : 1);
+					vga.crtc.disp_enable_skew = (data & 0x60) >> 5;
+					vga.crtc.evra = (data & 0x80) >> 7;
+					return;
+				case 0x04:
+					if(vga.crtc.protect_enable)
+						return;
+					vga.crtc.horz_retrace_start = data / (m_interlace && !(vga.sequencer.data[0x25] & 0x20) ? 2 : 1);
+					return;
+				case 0x05:
+					if(vga.crtc.protect_enable)
+						return;
+					vga.crtc.horz_blank_end = m_crtc_regs[0x05] & 0x1f;
+					vga.crtc.horz_blank_end |= ((data & 0x80) >> 2);
+					vga.crtc.horz_blank_end /= (m_interlace && !(vga.sequencer.data[0x25] & 0x20) ? 2 : 1);
+					vga.crtc.horz_retrace_skew = ((data & 0x60) >> 5);
+					vga.crtc.horz_retrace_end = data & 0x1f;
+					return;
+				case 0x06:
+					if(vga.crtc.protect_enable)
+						return;
+					vga.crtc.vert_total = ((m_crtc_regs[0x07] & 0x20) << (9-6)) | ((m_crtc_regs[0x07] & 0x01) << (8-0));
+					vga.crtc.vert_total |= data;
+					vga.crtc.vert_total *= (m_interlace ? 2 : 1);
+					recompute_params();
+					return;
+				case 0x07: // Overflow Register
+					vga.crtc.line_compare       &= ~0x100;
+					vga.crtc.line_compare       |= ((data & 0x10) << (8-4));
+					if(vga.crtc.protect_enable)
+						return;
+					vga.crtc.vert_total         = m_crtc_regs[0x05];
+					vga.crtc.vert_retrace_start = m_crtc_regs[0x10];
+					vga.crtc.vert_disp_end      = m_crtc_regs[0x12];
+					vga.crtc.vert_blank_start   = m_crtc_regs[0x15] | ((m_crtc_regs[0x09] & 0x20) << (9-5));
+					vga.crtc.vert_retrace_start |= ((data & 0x80) << (9-7));
+					vga.crtc.vert_disp_end      |= ((data & 0x40) << (9-6));
+					vga.crtc.vert_total         |= ((data & 0x20) << (9-5));
+					vga.crtc.vert_blank_start   |= ((data & 0x08) << (8-3));
+					vga.crtc.vert_retrace_start |= ((data & 0x04) << (8-2));
+					vga.crtc.vert_disp_end      |= ((data & 0x02) << (8-1));
+					vga.crtc.vert_total         |= ((data & 0x01) << (8-0));
+					vga.crtc.vert_total *= (m_interlace ? 2 : 1);
+					vga.crtc.vert_blank_start *= (m_interlace ? 2 : 1);
+					vga.crtc.vert_retrace_start *= (m_interlace ? 2 : 1);
+					vga.crtc.vert_disp_end *= (m_interlace ? 2 : 1);
+					recompute_params();
+					return;
+				case 0x09: // Maximum Scan Line Register
+					vga.crtc.line_compare      &= ~0x200;
+					vga.crtc.vert_blank_start  = m_crtc_regs[0x15] | ((m_crtc_regs[0x07] & 0x02) << (8-3));
+					vga.crtc.scan_doubling      = ((data & 0x80) >> 7);
+					vga.crtc.line_compare      |= ((data & 0x40) << (9-6));
+					vga.crtc.vert_blank_start  |= ((data & 0x20) << (9-5));
+					vga.crtc.maximum_scan_line  = (data & 0x1f) + 1;
+					vga.crtc.vert_blank_start *= (m_interlace ? 2 : 1);
+					return;
+				case 0x10:
+					vga.crtc.vert_retrace_start = ((m_crtc_regs[0x07] & 0x80) << (9-7)) | ((m_crtc_regs[0x07] & 0x40) << (8-2));
+					vga.crtc.vert_retrace_start |= data;
+					vga.crtc.vert_retrace_start *= (m_interlace ? 2 : 1);
+					return;
+				case 0x12:
+					vga.crtc.vert_disp_end = ((m_crtc_regs[0x07] & 0x40) << (9-6)) | ((m_crtc_regs[0x07] & 0x02) << (8-1));
+					vga.crtc.vert_disp_end |= data;
+					vga.crtc.vert_disp_end *= (m_interlace ? 2 : 1);
+					recompute_params();
+					return;
+				case 0x15:
+					vga.crtc.vert_blank_start = ((m_crtc_regs[0x09] & 0x20) << (9-5)) | ((m_crtc_regs[0x07] & 0x02) << (8-3));
+					vga.crtc.vert_blank_start |= data;
+					vga.crtc.vert_blank_start *= (m_interlace ? 2 : 1);
+					return;
+				case 0x16:
+					vga.crtc.vert_blank_end = (data & 0x7f) * (m_interlace ? 2 : 1);
+					return;
 				case 0x14:
 					m_dw = data & 0x40 ? 1 : 0;
-					if(vga.sequencer.data[0x1f] | 0x10)
+					if(vga.sequencer.data[0x1f] & 0x10)
 						data |= 0x40;
 					break;
 				case 0x30:
-					m_interlace = data; // XXX: verify?
+					if(data && !m_interlace)
+					{
+						if(!(vga.sequencer.data[0x25] & 0x20))
+						{
+							vga.crtc.horz_total /= 2;
+							vga.crtc.horz_disp_end /= 2;
+							vga.crtc.horz_blank_end /= 2;
+							vga.crtc.horz_retrace_start /= 2;
+							vga.crtc.horz_retrace_end /= 2;
+						}
+						vga.crtc.vert_total *= 2;
+						vga.crtc.vert_retrace_start *= 2;
+						vga.crtc.vert_disp_end *= 2;
+						vga.crtc.vert_blank_start *= 2;
+						vga.crtc.vert_blank_end *= 2;
+						recompute_params();
+					}
+					else if(!data && m_interlace)
+					{
+						if(!(vga.sequencer.data[0x25] & 0x20))
+						{
+							vga.crtc.horz_total *= 2;
+							vga.crtc.horz_disp_end *= 2;
+							vga.crtc.horz_blank_end *= 2;
+							vga.crtc.horz_retrace_start *= 2;
+							vga.crtc.horz_retrace_end *= 2;
+						}
+						vga.crtc.vert_total /= 2;
+						vga.crtc.vert_retrace_start /= 2;
+						vga.crtc.vert_disp_end /= 2;
+						vga.crtc.vert_blank_start /= 2;
+						vga.crtc.vert_blank_end /= 2;
+						recompute_params();
+					}
+					m_interlace = data;
 					return;
 			}
 			break;
diff --git a/src/mame/drivers/vpoker.cpp b/src/mame/drivers/vpoker.cpp
index e11c517..7f21739 100644
--- a/src/mame/drivers/vpoker.cpp
+++ b/src/mame/drivers/vpoker.cpp
@@ -647,8 +647,7 @@ static MACHINE_CONFIG_START( vpoker, vpoker_state )
 	MCFG_PALETTE_ADD_3BIT_GBR("palette")
 
 	/* 6840 PTM */
-	MCFG_DEVICE_ADD("6840ptm", PTM6840, 0)
-	MCFG_PTM6840_INTERNAL_CLOCK(XTAL_4MHz)
+	MCFG_DEVICE_ADD("6840ptm", PTM6840, XTAL_4MHz)
 	MCFG_PTM6840_EXTERNAL_CLOCKS(0, 0, 0)
 	MCFG_PTM6840_IRQ_CB(WRITELINE(vpoker_state, ptm_irq))
 
diff --git a/src/mame/drivers/vt100.cpp b/src/mame/drivers/vt100.cpp
index ac516d9..cec62a4 100644
--- a/src/mame/drivers/vt100.cpp
+++ b/src/mame/drivers/vt100.cpp
@@ -665,10 +665,10 @@ ROM_START( vt100ac ) // This is from the VT180 technical manual at http://www.bi
 // on page 433: VT100 WC or WK uses these as well.
 // This romset adds the Set-up C page to the setup menu (press keypad 5 twice once you hit set-up)
 	ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASEFF )
-	ROM_LOAD( "23-095e2.e40", 0x0000, 0x0800, CRC(6C8ACF44) SHA1(B3EF5AF920995A40A316C6DC008960C461853BFC)) // Label: "23095E2 // (C)DEC // (M)QQ8227" @E40
-	ROM_LOAD( "23-096e2.e45", 0x0800, 0x0800, CRC(77F21473) SHA1(6F10B250777C12CCA63EE611735F9F36CC05A7EF)) // Label: "23096E2 // (C)DEC // (M)QQ8227" @E45
-	ROM_LOAD( "23-139e2.bad3.e52", 0x1000, 0x0800, BAD_DUMP CRC(EAEDE07A) SHA1(410CEF41C4F3A6A37570A82F359DD2B2D536D3DD)) // Label: "AMD // 37108 8232DKP // 23-139E2 // AM9218CPC // (C)DEC_1979" @E52;  // revision 2?; revision 1 is 23-097e2 MAYBE // bytes with A1 and A2 both high and a3 high? are mostly correct, rest are likely all wrong.
-	ROM_LOAD( "23-140e2.e56", 0x1800, 0x0800, CRC(4BF1CE4E) SHA1(279F47EC9A68C801C3C05005DD782202AC9E51A4)) // Label: "AMD // 37109 8230DHP // 23-140E2 // AM9218CPC // (C)DEC 1979" @E56  // revision 2?; revision 1 is 23-098e2 MAYBE
+	ROM_LOAD( "23-095e2.e40", 0x0000, 0x0800, CRC(6c8acf44) SHA1(b3ef5af920995a40a316c6dc008960c461853bfc)) // Label: "23095E2 // (C)DEC // (M)QQ8227" @E40
+	ROM_LOAD( "23-096e2.e45", 0x0800, 0x0800, CRC(77f21473) SHA1(6f10b250777c12cca63ee611735f9f36cc05a7ef)) // Label: "23096E2 // (C)DEC // (M)QQ8227" @E45
+	ROM_LOAD( "23-139e2.bad3.e52", 0x1000, 0x0800, BAD_DUMP CRC(eaede07a) SHA1(410cef41c4f3a6a37570a82f359dd2b2d536d3dd)) // Label: "AMD // 37108 8232DKP // 23-139E2 // AM9218CPC // (C)DEC_1979" @E52;  // revision 2?; revision 1 is 23-097e2 MAYBE // bytes with A1 and A2 both high and a3 high? are mostly correct, rest are likely all wrong.
+	ROM_LOAD( "23-140e2.e56", 0x1800, 0x0800, CRC(4bf1ce4e) SHA1(279f47ec9a68c801c3c05005dd782202ac9e51a4)) // Label: "AMD // 37109 8230DHP // 23-140E2 // AM9218CPC // (C)DEC 1979" @E56  // revision 2?; revision 1 is 23-098e2 MAYBE
 
 	/* bad rom tracing
 	bpset 1be then set pc=1d5 to bypass rom test
@@ -679,11 +679,11 @@ ROM_START( vt100ac ) // This is from the VT180 technical manual at http://www.bi
 	ROM_REGION(0x1000, "avo", 0) // all switches on avo are open EXCEPT S2-3; does this map at 0xa000-0xcfff (mirrored) in maincpu space?
 	// are 184 and 185 an older version of the stp avo firmware?
 	//NOTE: for both of these two avo roms, Pin 18 is positive enable CE, Pin 20 is negative enable /CE1, Pin 21 is negative enable /CE2,
-	ROM_LOAD( "23-186e2.avo.e21", 0x0000, 0x0800, CRC(1592DEC1) SHA1(C4B8FC9FC0514E0CD46AD2DE03ABE72271CE460B)) // Label: "S 8218 // C69063 // 23186E2" @E21
-	ROM_LOAD( "23-187e2.avo.e17", 0x0800, 0x0800, CRC(C6D72A41) SHA1(956F9EB945A250FD05C76100B38C0BA381AB8FDE)) // Label: "S 8228 // C69062 // 23187E2" @E17
+	ROM_LOAD( "23-186e2.avo.e21", 0x0000, 0x0800, CRC(1592dec1) SHA1(c4b8fc9fc0514e0cd46ad2de03abe72271ce460b)) // Label: "S 8218 // C69063 // 23186E2" @E21
+	ROM_LOAD( "23-187e2.avo.e17", 0x0800, 0x0800, CRC(c6d72a41) SHA1(956f9eb945a250fd05c76100b38c0ba381ab8fde)) // Label: "S 8228 // C69062 // 23187E2" @E17
 
 	ROM_REGION(0x2000, "stp", 0) // stp switches 1 and 5 are closed, 2,3,4 open
-	ROM_LOAD( "23-029e4.stp.e14", 0x0000, 0x2000, CRC(DA55C62B) SHA1(261B02B774D57253D1DEDECAB8CA0E368C2A96CD)) // Label: "S 8218 // C43020 // 23029E4 (C) DEC // TP02" @E14
+	ROM_LOAD( "23-029e4.stp.e14", 0x0000, 0x2000, CRC(da55c62b) SHA1(261b02b774d57253d1dedecab8ca0e368c2a96cd)) // Label: "S 8218 // C43020 // 23029E4 (C) DEC // TP02" @E14
 	// the rom dump above MIGHT be in the wrong order: it was dumped with A11 to pin 18, A12 to pin 21, A13 to pin 20, but I'm not sure those assignments to pins are correct.
 	// At worst the 8 parts of it are in the wrong order.
 
diff --git a/src/mame/drivers/whitestar.cpp b/src/mame/drivers/whitestar.cpp
index 592afc5..3580b60 100644
--- a/src/mame/drivers/whitestar.cpp
+++ b/src/mame/drivers/whitestar.cpp
@@ -1015,6 +1015,23 @@ ROM_START(lostspc)
 	ROM_LOAD("lisu37.100", 0x180000, 0x80000, CRC(f9430c59) SHA1(f0f7169e63fc12d29fe39cd24dd67c5fb17779f7))
 ROM_END
 
+ROM_START(lostspcf)
+	ROM_REGION(0x80000, "user1", 0)
+	ROM_LOAD("liscpu.101", 0x00000, 0x20000, CRC(81b2ced8) SHA1(a1933e2686b2a4e48d0f327593df95a927b132cb))
+	ROM_RELOAD(0x20000, 0x20000)
+	ROM_RELOAD(0x40000, 0x20000)
+	ROM_RELOAD(0x60000, 0x20000)
+	ROM_REGION(0x80000, "dmdcpu", 0)
+	ROM_LOAD("lis_f-102.bin", 0x00000, 0x80000, CRC(422ba6d5) SHA1(0cd09b14a953fda39f8c7e5521c4115d2ada9186))
+	ROM_REGION(0x010000, "soundcpu", 0)
+	ROM_LOAD("lisu7.100", 0x0000, 0x10000, CRC(96e6b3c4) SHA1(5cfb43b8c182aed4b49ad1b8803812a18c6c8b6f))
+	ROM_REGION(0x1000000, "bsmt", 0 )
+	ROM_LOAD("lisu17.100", 0x000000, 0x80000, CRC(69076939) SHA1(f2cdf61a2b469d1a69eb3f08fc6e511d72336586))
+	ROM_LOAD("lisu21.100", 0x080000, 0x80000, CRC(56eede09) SHA1(9ff53d7a188bd7293ad92089d143bd54623a50d4))
+	ROM_LOAD("lisu36.100", 0x100000, 0x80000, CRC(56f2c53b) SHA1(5c2daf17116016fbead1320eb150cf655984662b))
+	ROM_LOAD("lisu37.100", 0x180000, 0x80000, CRC(f9430c59) SHA1(f0f7169e63fc12d29fe39cd24dd67c5fb17779f7))
+ROM_END
+
 ROM_START(lostspcg)
 	ROM_REGION(0x80000, "user1", 0)
 	ROM_LOAD("liscpu.101", 0x00000, 0x20000, CRC(81b2ced8) SHA1(a1933e2686b2a4e48d0f327593df95a927b132cb))
@@ -3167,6 +3184,21 @@ ROM_START(xfilesp)
 	ROM_LOAD("xfsndu21.c40", 0x080000, 0x80000, CRC(b56a5ca6) SHA1(5fa23a8bb57e45aca159882226e603d9a6be078b))
 ROM_END
 
+ROM_START(xfilespf)
+	ROM_REGION(0x80000, "user1", 0)
+	ROM_LOAD("xfcpu.303", 0x00000, 0x20000, CRC(c7ab5efe) SHA1(dcb4b89adfb5ba39e59c1118a00b29941d3ea4e9))
+	ROM_RELOAD(0x20000, 0x20000)
+	ROM_RELOAD(0x40000, 0x20000)
+	ROM_RELOAD(0x60000, 0x20000)
+	ROM_REGION(0x80000, "dmdcpu", 0)
+	ROM_LOAD("xfildspf.300", 0x00000, 0x80000, CRC(fe9b1292) SHA1(ead40d2cdff060829008f468e08512c4f5f9e055))
+	ROM_REGION(0x010000, "soundcpu", 0)
+	ROM_LOAD("xfsndu7.512", 0x0000, 0x10000, CRC(01d65239) SHA1(9e680de940a15ef85a5615b789c58cd5973ff11b))
+	ROM_REGION(0x1000000, "bsmt", 0)
+	ROM_LOAD("xfsndu17.c40", 0x000000, 0x80000, CRC(40bfc835) SHA1(2d6ac82acbbf9645bcb84fab7f285f2373e516a8))
+	ROM_LOAD("xfsndu21.c40", 0x080000, 0x80000, CRC(b56a5ca6) SHA1(5fa23a8bb57e45aca159882226e603d9a6be078b))
+ROM_END
+
 ROM_START(xfiles2)
 	ROM_REGION(0x80000, "user1", 0)
 	ROM_LOAD("xfcpu.204", 0x00000, 0x20000, CRC(a4913128) SHA1(1fe348725e13fd5dc56b6b2dbd173d0b49953483))
@@ -3405,8 +3437,9 @@ GAME(1996,  id4f,       id4,        whitestar,  whitestar, driver_device, 0,  RO
 GAME(1996,  id4_201,    id4,        whitestar,  whitestar, driver_device, 0,  ROT0,   "Sega",     "Independence Day (v2.01)",             MACHINE_IS_PINBALL)
 GAME(1996,  id4f_201,   id4,        whitestar,  whitestar, driver_device, 0,  ROT0,   "Sega",     "Independence Day (v2.01 France)",      MACHINE_IS_PINBALL)
 GAME(1998,  lostspc,    0,          whitestar,  whitestar, driver_device, 0,  ROT0,   "Sega",     "Lost in Space (1.01)",                MACHINE_IS_PINBALL)
+GAME(1998,  lostspcf,   lostspc,    whitestar,  whitestar, driver_device, 0,  ROT0,   "Sega",     "Lost in Space (1.01 France)",        MACHINE_IS_PINBALL)
 GAME(1998,  lostspcg,   lostspc,    whitestar,  whitestar, driver_device, 0,  ROT0,   "Sega",     "Lost in Space (1.01 Germany)",        MACHINE_IS_PINBALL)
-GAME(1998,  lostspc_d1, lostspc,    whitestar,  whitestar, driver_device, 0,  ROT0,   "Sega",     "Lost in Space (1.01, Display 1.02)",  MACHINE_IS_PINBALL)
+GAME(1998,  lostspc_d1, lostspc,    whitestar,  whitestar, driver_device, 0,  ROT0,   "Sega",     "Lost in Space (1.01, Display 1.01)",  MACHINE_IS_PINBALL)
 GAME(2001,  monopolp,   0,          whitestar,  whitestar, driver_device, 0,  ROT0,   "Stern",    "Monopoly (3.20)",              MACHINE_IS_PINBALL)
 GAME(2002,  monop303,   monopolp,   whitestar,  whitestar, driver_device, 0,  ROT0,   "Stern",    "Monopoly (3.03)",              MACHINE_IS_PINBALL)
 GAME(2002,  monop301,   monopolp,   whitestar,  whitestar, driver_device, 0,  ROT0,   "Stern",    "Monopoly (3.01)",              MACHINE_IS_PINBALL)
@@ -3534,6 +3567,7 @@ GAME(2003,  simpprti_400,simpprti,  whitestar,  whitestar, driver_device, 0,  RO
 GAME(2003,  simpprti_300,simpprti,  whitestar,  whitestar, driver_device, 0,  ROT0,   "Stern",    "The Simpsons Pinball Party (3.00 Italy)",             MACHINE_IS_PINBALL)
 GAME(2003,  simpprti_204,simpprti,  whitestar,  whitestar, driver_device, 0,  ROT0,   "Stern",    "The Simpsons Pinball Party (2.04 Italy)",             MACHINE_IS_PINBALL)
 GAME(1997,  xfilesp,    0,          whitestar,  whitestar, driver_device, 0,  ROT0,   "Sega",     "X-Files (3.03)",               MACHINE_IS_PINBALL)
+GAME(1997,  xfilespf,   xfilesp,    whitestar,  whitestar, driver_device, 0,  ROT0,   "Sega",     "X-Files (3.03 France)",        MACHINE_IS_PINBALL)
 GAME(1997,  xfiles2,    xfilesp,    whitestar,  whitestar, driver_device, 0,  ROT0,   "Sega",     "X-Files (2.04)",               MACHINE_IS_PINBALL)
 GAME(1997,  xfiles20,   xfilesp,    whitestar,  whitestar, driver_device, 0,  ROT0,   "Sega",     "X-Files (2.00)",               MACHINE_IS_PINBALL)
 GAME(1996,  twst_405,   0,          whitestar,  whitestar, driver_device, 0,  ROT0,   "Sega",     "Twister (4.05)",               MACHINE_IS_PINBALL)
diff --git a/src/mame/drivers/witch.cpp b/src/mame/drivers/witch.cpp
index d9b9054..080af26 100644
--- a/src/mame/drivers/witch.cpp
+++ b/src/mame/drivers/witch.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /*
 
diff --git a/src/mame/drivers/xbox.cpp b/src/mame/drivers/xbox.cpp
index bcc5ffb..c187622 100644
--- a/src/mame/drivers/xbox.cpp
+++ b/src/mame/drivers/xbox.cpp
@@ -22,7 +22,7 @@
 #include "debug/debugcon.h"
 #include "debug/debugcmd.h"
 #include "debugger.h"
-#include "includes/chihiro.h"
+#include "includes/xbox_nv2a.h"
 #include "includes/xbox.h"
 #include "includes/xbox_usb.h"
 
@@ -149,7 +149,7 @@ void xbox_state::machine_reset()
 	atapi_cdrom_device *devc;
 	uint16_t *id;
 
-	// set some neede parameters
+	// set some needed parameters
 	devh = machine().device<ata_mass_storage_device>("ide:0:hdd");
 	id = devh->identify_device_buffer();
 	id[88] |= (1 << 2); // ultra dma mode 2 supported
@@ -215,9 +215,9 @@ ROM_START( xbox )
 
 	ROM_REGION( 0x1000000, "tbp", 0 ) // To Be Processed, of course
 	ROM_LOAD( "5101_256k.bin", 0x000000, 0x040000, CRC(e8a9224e) SHA1(5108e1025f48071c07a6823661d708c66dee97a9) )
-	ROM_LOAD( "xbox-5530.bin", 0x000000, 0x040000, CRC(9569c4d3) SHA1(40fa73277013be3168135e1768b09623a987ff63) )
-	ROM_LOAD( "xbox-5713.bin", 0x040000, 0x040000, CRC(58fd8173) SHA1(8b7ccc4648ccd78cdb7b65cfca09621eaf2d4238) )
-	ROM_LOAD( "5838_256k.bin", 0x000000, 0x040000, CRC(5be2413d) SHA1(b9489e883c650b5e5fe2f83a32237dbf74f0e9f1) )
+	ROM_LOAD( "xbox-5530.bin", 0x040000, 0x040000, CRC(9569c4d3) SHA1(40fa73277013be3168135e1768b09623a987ff63) )
+	ROM_LOAD( "xbox-5713.bin", 0x080000, 0x040000, CRC(58fd8173) SHA1(8b7ccc4648ccd78cdb7b65cfca09621eaf2d4238) )
+	ROM_LOAD( "5838_256k.bin", 0x0C0000, 0x040000, CRC(5be2413d) SHA1(b9489e883c650b5e5fe2f83a32237dbf74f0e9f1) )
 ROM_END
 // See src/emu/gamedrv.h for details
 // For a game:
diff --git a/src/mame/drivers/yunsung8.cpp b/src/mame/drivers/yunsung8.cpp
index 9d5f12b..22ea8b1 100644
--- a/src/mame/drivers/yunsung8.cpp
+++ b/src/mame/drivers/yunsung8.cpp
@@ -25,10 +25,6 @@ Notes:
 - "Magix" can change title to "Rock" through a DSW
 - In service mode press Service Coin (e.g. '9')
 
-To Do:
-
-- Better Sound
-
 ***************************************************************************/
 
 #include "emu.h"
@@ -56,6 +52,23 @@ WRITE8_MEMBER(yunsung8_state::bankswitch_w)
 		logerror("CPU #0 - PC %04X: Bank %02X\n", space.device().safe_pc(), data);
 }
 
+READ8_MEMBER(yunsung8_state::sound_command_r)
+{
+	m_audiocpu->set_input_line(0, CLEAR_LINE);
+	return m_soundlatch->read(space, 0);
+}
+
+WRITE8_MEMBER(yunsung8_state::sound_command_w)
+{
+	m_soundlatch->write(space, 0, data);
+	m_audiocpu->set_input_line(0, ASSERT_LINE);
+}
+
+WRITE8_MEMBER(yunsung8_state::main_irq_ack_w)
+{
+	m_maincpu->set_input_line(0, CLEAR_LINE);
+}
+
 /*
     Banked Video RAM:
 
@@ -78,11 +91,11 @@ static ADDRESS_MAP_START( port_map, AS_IO, 8, yunsung8_state )
 	ADDRESS_MAP_GLOBAL_MASK(0xff)
 	AM_RANGE(0x00, 0x00) AM_READ_PORT("SYSTEM") AM_WRITE(videobank_w)  // video RAM bank
 	AM_RANGE(0x01, 0x01) AM_READ_PORT("P1") AM_WRITE(bankswitch_w) // ROM Bank + Layers Enable
-	AM_RANGE(0x02, 0x02) AM_READ_PORT("P2") AM_DEVWRITE("soundlatch", generic_latch_8_device, write) // To Sound CPU
+	AM_RANGE(0x02, 0x02) AM_READ_PORT("P2") AM_WRITE(sound_command_w) // To Sound CPU
 	AM_RANGE(0x03, 0x03) AM_READ_PORT("DSW1")
 	AM_RANGE(0x04, 0x04) AM_READ_PORT("DSW2")
 	AM_RANGE(0x06, 0x06) AM_WRITE(flipscreen_w)    // Flip Screen
-	AM_RANGE(0x07, 0x07) AM_WRITENOP    // ? (end of IRQ, random value)
+	AM_RANGE(0x07, 0x07) AM_WRITE(main_irq_ack_w)
 ADDRESS_MAP_END
 
 
@@ -105,22 +118,16 @@ WRITE8_MEMBER(yunsung8_state::sound_bankswitch_w)
 		logerror("%s: Bank %02X\n", machine().describe_context(), data);
 }
 
-WRITE8_MEMBER(yunsung8_state::adpcm_w)
-{
-	/* Swap the nibbles */
-	m_adpcm = ((data & 0xf) << 4) | ((data >> 4) & 0xf);
-}
-
 
 
 static ADDRESS_MAP_START( sound_map, AS_PROGRAM, 8, yunsung8_state )
 	AM_RANGE(0x0000, 0x7fff) AM_ROM
-	AM_RANGE(0x8000, 0xbfff) AM_ROMBANK("soundbank")    // Banked ROM
-	AM_RANGE(0xe000, 0xe000) AM_WRITE(sound_bankswitch_w   )   // ROM Bank
-	AM_RANGE(0xe400, 0xe400) AM_WRITE(adpcm_w)
+	AM_RANGE(0x8000, 0xbfff) AM_ROMBANK("soundbank")      // Banked ROM
+	AM_RANGE(0xe000, 0xe000) AM_WRITE(sound_bankswitch_w) // ROM Bank
+	AM_RANGE(0xe400, 0xe400) AM_DEVWRITE("adpcm_select", ls157_device, ba_w)
 	AM_RANGE(0xec00, 0xec01) AM_DEVWRITE("ymsnd", ym3812_device, write)
 	AM_RANGE(0xf000, 0xf7ff) AM_RAM
-	AM_RANGE(0xf800, 0xf800) AM_DEVREAD("soundlatch", generic_latch_8_device, read) // From Main CPU
+	AM_RANGE(0xf800, 0xf800) AM_READ(sound_command_r) // From Main CPU
 ADDRESS_MAP_END
 
 
@@ -134,26 +141,26 @@ ADDRESS_MAP_END
 
 ***************************************************************************/
 
+
 /***************************************************************************
-                                    Magix
+                                    Rock Tris
 ***************************************************************************/
-
-static INPUT_PORTS_START( magix )
+static INPUT_PORTS_START( rocktris )
 	PORT_START("SYSTEM")
 	PORT_BIT(  0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )
 	PORT_BIT(  0x02, IP_ACTIVE_LOW, IPT_START2 )
 	PORT_BIT(  0x04, IP_ACTIVE_LOW, IPT_UNKNOWN )
 	PORT_BIT(  0x08, IP_ACTIVE_LOW, IPT_START1 )
 	PORT_BIT(  0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
-	PORT_BIT(  0x20, IP_ACTIVE_LOW, IPT_SERVICE1 )
+	PORT_BIT(  0x20, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_IMPULSE(1)
 	PORT_BIT(  0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
-	PORT_BIT(  0x80, IP_ACTIVE_LOW, IPT_COIN1 )
+	PORT_BIT(  0x80, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_IMPULSE(1)
 
 	PORT_START("P1")
 	PORT_BIT(  0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )
 	PORT_BIT(  0x02, IP_ACTIVE_LOW, IPT_UNKNOWN )
-	PORT_BIT(  0x04, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1)    // same as button1 !?
-	PORT_BIT(  0x08, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1)
+	PORT_BIT(  0x04, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) // Bomb
+	PORT_BIT(  0x08, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) // Rotate
 	PORT_BIT(  0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1)
 	PORT_BIT(  0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1)
 	PORT_BIT(  0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1)
@@ -162,8 +169,8 @@ static INPUT_PORTS_START( magix )
 	PORT_START("P2")
 	PORT_BIT(  0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )
 	PORT_BIT(  0x02, IP_ACTIVE_LOW, IPT_UNKNOWN )
-	PORT_BIT(  0x04, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2)    // same as button1 !?
-	PORT_BIT(  0x08, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
+	PORT_BIT(  0x04, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) // Bomb
+	PORT_BIT(  0x08, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) // Rotate
 	PORT_BIT(  0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2)
 	PORT_BIT(  0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2)
 	PORT_BIT(  0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2)
@@ -193,10 +200,10 @@ static INPUT_PORTS_START( magix )
 	PORT_DIPSETTING(    0x80, DEF_STR( 1C_4C ) )
 
 	PORT_START("DSW2")
-	PORT_DIPNAME( 0x01, 0x01, "Title" )
-	PORT_DIPSETTING(    0x01, "Magix" )
-	PORT_DIPSETTING(    0x00, "Rock" )
-	PORT_DIPNAME( 0x02, 0x02, "Unknown 2-1" )   // the rest seems unused
+	PORT_DIPNAME( 0x01, 0x01, "Unknown 2-0" )   // the rest seems unused
+	PORT_DIPSETTING(    0x01, DEF_STR( Off ) )
+	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
+	PORT_DIPNAME( 0x02, 0x02, "Unknown 2-1" )
 	PORT_DIPSETTING(    0x02, DEF_STR( Off ) )
 	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
 	PORT_DIPNAME( 0x04, 0x04, "Unknown 2-2" )
@@ -219,183 +226,46 @@ static INPUT_PORTS_START( magix )
 	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
 INPUT_PORTS_END
 
+/***************************************************************************
+                                    Magix
+***************************************************************************/
+static INPUT_PORTS_START( magix )
+	PORT_INCLUDE(rocktris) // BTN1 = Rotate, BTN2 = Rotate (Again! ...same dir as BTN1)
+
+	PORT_MODIFY("DSW2")
+	PORT_DIPNAME( 0x01, 0x01, "Title" )
+	PORT_DIPSETTING(    0x01, "Magix" )
+	PORT_DIPSETTING(    0x00, "Rock" )
+INPUT_PORTS_END
 
 /***************************************************************************
                                 Cannon Ball
 ***************************************************************************/
-
 static INPUT_PORTS_START( cannball )
-	PORT_START("SYSTEM")
-	PORT_BIT(  0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )
-	PORT_BIT(  0x02, IP_ACTIVE_LOW, IPT_START2 )
-	PORT_BIT(  0x04, IP_ACTIVE_LOW, IPT_UNKNOWN )
-	PORT_BIT(  0x08, IP_ACTIVE_LOW, IPT_START1 )
-	PORT_BIT(  0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
-	PORT_BIT(  0x20, IP_ACTIVE_LOW, IPT_SERVICE1 )
-	PORT_BIT(  0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
-	PORT_BIT(  0x80, IP_ACTIVE_LOW, IPT_COIN1 )
+	PORT_INCLUDE(rocktris)
 
-	PORT_START("P1")
-	PORT_BIT(  0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )
-	PORT_BIT(  0x02, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1)
-	PORT_BIT(  0x04, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1)
-	PORT_BIT(  0x08, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1)
-	PORT_BIT(  0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1)
-	PORT_BIT(  0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1)
-	PORT_BIT(  0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1)
-	PORT_BIT(  0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1)
+	PORT_MODIFY("P1")
+	PORT_BIT(  0x02, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) // BTN1 = Launch, BTN2 = Rotate, BTN3 = Bomb
 
-	PORT_START("P2")
-	PORT_BIT(  0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )
-	PORT_BIT(  0x02, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2)
-	PORT_BIT(  0x04, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2)
-	PORT_BIT(  0x08, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
-	PORT_BIT(  0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2)
-	PORT_BIT(  0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2)
-	PORT_BIT(  0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2)
-	PORT_BIT(  0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2)
-
-	PORT_START("DSW1")
-	PORT_SERVICE( 0x01, IP_ACTIVE_LOW )
-	PORT_DIPNAME( 0x06, 0x06, DEF_STR( Difficulty ) )
-	PORT_DIPSETTING(    0x00, DEF_STR( Easy ) )
-	PORT_DIPSETTING(    0x06, DEF_STR( Normal ) )
-	PORT_DIPSETTING(    0x04, DEF_STR( Hard ) )
-	PORT_DIPSETTING(    0x02, DEF_STR( Hardest ) )
-	PORT_DIPNAME( 0x08, 0x08, DEF_STR( Flip_Screen ) )
-	PORT_DIPSETTING(    0x08, DEF_STR( Off ) )
-	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
-	PORT_DIPNAME( 0x10, 0x00, DEF_STR( Demo_Sounds ) )
-	PORT_DIPSETTING(    0x10, DEF_STR( Off ) )
-	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
-	PORT_DIPNAME( 0xe0, 0xe0, DEF_STR( Coinage ) )
-	PORT_DIPSETTING(    0x00, DEF_STR( 4C_1C ) )
-	PORT_DIPSETTING(    0x20, DEF_STR( 3C_1C ) )
-	PORT_DIPSETTING(    0x60, DEF_STR( 2C_1C ) )
-	PORT_DIPSETTING(    0xe0, DEF_STR( 1C_1C ) )
-	PORT_DIPSETTING(    0x40, DEF_STR( 2C_3C ) )
-	PORT_DIPSETTING(    0xc0, DEF_STR( 1C_2C ) )
-	PORT_DIPSETTING(    0xa0, DEF_STR( 1C_3C ) )
-	PORT_DIPSETTING(    0x80, DEF_STR( 1C_4C ) )
+	PORT_MODIFY("P2")
+	PORT_BIT(  0x02, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) // BTN1 = Launch, BTN2 = Rotate, BTN3 = Bomb
 
-	PORT_START("DSW2")
-	PORT_DIPNAME( 0x01, 0x01, "Unknown 2-0" )
-	PORT_DIPSETTING(    0x01, DEF_STR( Off ) )
-	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
-	PORT_DIPNAME( 0x02, 0x02, "Unknown 2-1" )
-	PORT_DIPSETTING(    0x02, DEF_STR( Off ) )
-	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
+	PORT_MODIFY("DSW2")
 	PORT_DIPNAME( 0x0c, 0x0c, "Bombs" )
 	PORT_DIPSETTING(    0x04, "1" )
 	PORT_DIPSETTING(    0x08, "2" )
 	PORT_DIPSETTING(    0x0c, "3" )
 	PORT_DIPSETTING(    0x00, "4" )
-	PORT_DIPNAME( 0x10, 0x10, "Unknown 2-4" )
-	PORT_DIPSETTING(    0x10, DEF_STR( Off ) )
-	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
-	PORT_DIPNAME( 0x20, 0x20, "Unknown 2-5" )
-	PORT_DIPSETTING(    0x20, DEF_STR( Off ) )
-	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
-	PORT_DIPNAME( 0x40, 0x40, "Unknown 2-6" )
-	PORT_DIPSETTING(    0x40, DEF_STR( Off ) )
-	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
-	PORT_DIPNAME( 0x80, 0x80, "Unknown 2-7" )
-	PORT_DIPSETTING(    0x80, DEF_STR( Off ) )
-	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
 INPUT_PORTS_END
 
 static INPUT_PORTS_START( cannbalv )
 	PORT_INCLUDE(cannball)
+
 	PORT_MODIFY("SYSTEM")
 	PORT_BIT(  0x40, IP_ACTIVE_HIGH, IPT_SPECIAL  ) // always activated, otherwise the game resets. a simple check for horizontal / vertical version of the game?
 INPUT_PORTS_END
 
 /***************************************************************************
-                                    Rock Tris
-***************************************************************************/
-
-static INPUT_PORTS_START( rocktris )
-	PORT_START("SYSTEM")
-	PORT_BIT(  0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )
-	PORT_BIT(  0x02, IP_ACTIVE_LOW, IPT_START2 )
-	PORT_BIT(  0x04, IP_ACTIVE_LOW, IPT_UNKNOWN )
-	PORT_BIT(  0x08, IP_ACTIVE_LOW, IPT_START1 )
-	PORT_BIT(  0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
-	PORT_BIT(  0x20, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_IMPULSE(1)
-	PORT_BIT(  0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
-	PORT_BIT(  0x80, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_IMPULSE(1)
-
-	PORT_START("P1")
-	PORT_BIT(  0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )
-	PORT_BIT(  0x02, IP_ACTIVE_LOW, IPT_UNKNOWN )
-	PORT_BIT(  0x04, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1)    // same as button1 !?
-	PORT_BIT(  0x08, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1)
-	PORT_BIT(  0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1)
-	PORT_BIT(  0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1)
-	PORT_BIT(  0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1)
-	PORT_BIT(  0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1)
-
-	PORT_START("P2")
-	PORT_BIT(  0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )
-	PORT_BIT(  0x02, IP_ACTIVE_LOW, IPT_UNKNOWN )
-	PORT_BIT(  0x04, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2)    // same as button1 !?
-	PORT_BIT(  0x08, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
-	PORT_BIT(  0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2)
-	PORT_BIT(  0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2)
-	PORT_BIT(  0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2)
-	PORT_BIT(  0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2)
-
-	PORT_START("DSW1")
-	PORT_SERVICE( 0x01, IP_ACTIVE_LOW )
-	PORT_DIPNAME( 0x06, 0x06, DEF_STR( Difficulty ) )
-	PORT_DIPSETTING(    0x00, DEF_STR( Easy ) )
-	PORT_DIPSETTING(    0x06, DEF_STR( Normal ) )
-	PORT_DIPSETTING(    0x04, DEF_STR( Hard ) )
-	PORT_DIPSETTING(    0x02, DEF_STR( Hardest ) )
-	PORT_DIPNAME( 0x08, 0x08, DEF_STR( Flip_Screen ) )
-	PORT_DIPSETTING(    0x08, DEF_STR( Off ) )
-	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
-	PORT_DIPNAME( 0x10, 0x00, DEF_STR( Demo_Sounds ) )
-	PORT_DIPSETTING(    0x10, DEF_STR( Off ) )
-	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
-	PORT_DIPNAME( 0xe0, 0xe0, DEF_STR( Coinage ) )
-	PORT_DIPSETTING(    0x00, DEF_STR( 4C_1C ) )
-	PORT_DIPSETTING(    0x20, DEF_STR( 3C_1C ) )
-	PORT_DIPSETTING(    0x60, DEF_STR( 2C_1C ) )
-	PORT_DIPSETTING(    0xe0, DEF_STR( 1C_1C ) )
-	PORT_DIPSETTING(    0x40, DEF_STR( 2C_3C ) )
-	PORT_DIPSETTING(    0xc0, DEF_STR( 1C_2C ) )
-	PORT_DIPSETTING(    0xa0, DEF_STR( 1C_3C ) )
-	PORT_DIPSETTING(    0x80, DEF_STR( 1C_4C ) )
-
-	PORT_START("DSW2")
-	PORT_DIPNAME( 0x01, 0x01, "Unknown 2-0" )   // the rest seems unused
-	PORT_DIPSETTING(    0x01, DEF_STR( Off ) )
-	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
-	PORT_DIPNAME( 0x02, 0x02, "Unknown 2-1" )
-	PORT_DIPSETTING(    0x02, DEF_STR( Off ) )
-	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
-	PORT_DIPNAME( 0x04, 0x04, "Unknown 2-2" )
-	PORT_DIPSETTING(    0x04, DEF_STR( Off ) )
-	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
-	PORT_DIPNAME( 0x08, 0x08, "Unknown 2-3" )
-	PORT_DIPSETTING(    0x08, DEF_STR( Off ) )
-	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
-	PORT_DIPNAME( 0x10, 0x10, "Unknown 2-4" )
-	PORT_DIPSETTING(    0x10, DEF_STR( Off ) )
-	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
-	PORT_DIPNAME( 0x20, 0x20, "Unknown 2-5" )
-	PORT_DIPSETTING(    0x20, DEF_STR( Off ) )
-	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
-	PORT_DIPNAME( 0x40, 0x40, "Unknown 2-6" )
-	PORT_DIPSETTING(    0x40, DEF_STR( Off ) )
-	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
-	PORT_DIPNAME( 0x80, 0x80, "Unknown 2-7" )
-	PORT_DIPSETTING(    0x80, DEF_STR( Off ) )
-	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
-INPUT_PORTS_END
-
-/***************************************************************************
 
 
                                 Graphics Layouts
@@ -446,18 +316,18 @@ GFXDECODE_END
 
 WRITE_LINE_MEMBER(yunsung8_state::adpcm_int)
 {
-	m_msm->data_w(m_adpcm >> 4);
-	m_adpcm <<= 4;
+	if (!state)
+		return;
 
-	m_toggle ^= 1;
-	if (m_toggle)
-		m_audiocpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE);
+	m_toggle = !m_toggle;
+	m_adpcm_select->select_w(m_toggle);
+	m_audiocpu->set_input_line(INPUT_LINE_NMI, m_toggle);
 }
 
 void yunsung8_state::machine_start()
 {
-	m_videoram_0 = m_videoram + 0x0000; // Ram is banked
-	m_videoram_1 = m_videoram + 0x2000;
+	m_bg_vram = m_videoram + 0x0000; // Ram is banked
+	m_fg_vram = m_videoram + 0x2000;
 
 	membank("mainbank")->configure_entries(0, 8, memregion("maincpu")->base(), 0x4000);
 	membank("soundbank")->configure_entries(0, 8, memregion("audiocpu")->base(), 0x4000);
@@ -465,7 +335,6 @@ void yunsung8_state::machine_start()
 	save_item(NAME(m_videoram));
 	save_item(NAME(m_layers_ctrl));
 	save_item(NAME(m_videobank));
-	save_item(NAME(m_adpcm));
 	save_item(NAME(m_toggle));
 }
 
@@ -473,8 +342,7 @@ void yunsung8_state::machine_reset()
 {
 	m_videobank = 0;
 	m_layers_ctrl = 0;
-	m_adpcm = 0;
-	m_toggle = 0;
+	m_toggle = false;
 }
 
 
@@ -484,12 +352,10 @@ static MACHINE_CONFIG_START( yunsung8, yunsung8_state )
 	MCFG_CPU_ADD("maincpu", Z80, XTAL_16MHz/2)           /* Z80B @ 8MHz? */
 	MCFG_CPU_PROGRAM_MAP(main_map)
 	MCFG_CPU_IO_MAP(port_map)
-	MCFG_CPU_VBLANK_INT_DRIVER("screen", yunsung8_state,  irq0_line_hold)   /* No nmi routine */
+	MCFG_CPU_VBLANK_INT_DRIVER("screen", yunsung8_state, irq0_line_assert)   /* No nmi routine */
 
 	MCFG_CPU_ADD("audiocpu", Z80, XTAL_16MHz/4)          /* ? */
 	MCFG_CPU_PROGRAM_MAP(sound_map)
-	MCFG_CPU_VBLANK_INT_DRIVER("screen", yunsung8_state,  irq0_line_hold)   /* NMI caused by the MSM5205? */
-
 
 	/* video hardware */
 	MCFG_SCREEN_ADD("screen", RASTER)
@@ -510,6 +376,9 @@ static MACHINE_CONFIG_START( yunsung8, yunsung8_state )
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 1.0)
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 1.0)
 
+	MCFG_DEVICE_ADD("adpcm_select", LS157, 0)
+	MCFG_74157_OUT_CB(DEVWRITE8("msm", msm5205_device, data_w))
+
 	MCFG_SOUND_ADD("msm", MSM5205, XTAL_400kHz) /* verified on pcb */
 	MCFG_MSM5205_VCLK_CB(WRITELINE(yunsung8_state, adpcm_int)) /* interrupt function */
 	MCFG_MSM5205_PRESCALER_SELECTOR(MSM5205_S96_4B)      /* 4KHz, 4 Bits */
@@ -735,8 +604,8 @@ ROM_END
 
 ***************************************************************************/
 
-GAME( 1995,  cannball,  0,        yunsung8, cannball, driver_device, 0, ROT0,   "Yun Sung / Soft Vision", "Cannon Ball (Yun Sung, horizontal)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
-GAME( 1995,  cannballv, cannball, yunsung8, cannbalv, driver_device, 0, ROT270, "Yun Sung / T&K",         "Cannon Ball (Yun Sung, vertical)",   MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
-GAME( 1995,  magix,     0,        yunsung8, magix,    driver_device, 0, ROT0,   "Yun Sung",               "Magix / Rock",                       MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
-GAME( 1995,  magixb,    magix,    yunsung8, magix,    driver_device, 0, ROT0,   "Yun Sung",               "Magix / Rock (no copyright message)",MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) // was marked as bootleg, but has been seen on original PCBs
-GAME( 1994?, rocktris,  0,        yunsung8, rocktris, driver_device, 0, ROT0,   "Yun Sung",               "Rock Tris",                          MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
+GAME( 1995,  cannball,  0,        yunsung8, cannball, driver_device, 0, ROT0,   "Yun Sung / Soft Vision",    "Cannon Ball (Yun Sung, horizontal)",  MACHINE_SUPPORTS_SAVE )
+GAME( 1995,  cannballv, cannball, yunsung8, cannbalv, driver_device, 0, ROT270, "Yun Sung / J&K Production", "Cannon Ball (Yun Sung, vertical)",    MACHINE_SUPPORTS_SAVE )
+GAME( 1995,  magix,     0,        yunsung8, magix,    driver_device, 0, ROT0,   "Yun Sung",                  "Magix / Rock",                        MACHINE_SUPPORTS_SAVE )
+GAME( 1995,  magixb,    magix,    yunsung8, magix,    driver_device, 0, ROT0,   "Yun Sung",                  "Magix / Rock (no copyright message)", MACHINE_SUPPORTS_SAVE ) // was marked as bootleg, but has been seen on original PCBs
+GAME( 1994?, rocktris,  0,        yunsung8, rocktris, driver_device, 0, ROT0,   "Yun Sung",                  "Rock Tris",                           MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/drivers/zn.cpp b/src/mame/drivers/zn.cpp
index f06eb6a..31bc72c 100644
--- a/src/mame/drivers/zn.cpp
+++ b/src/mame/drivers/zn.cpp
@@ -2554,6 +2554,22 @@ static INPUT_PORTS_START( zn )
 	PORT_DIPUNKNOWN_DIPLOC( 0x08, 0x08, "S551:4" )
 INPUT_PORTS_END
 
+static INPUT_PORTS_START( nbajamex )
+	PORT_INCLUDE( zn )
+
+	PORT_MODIFY("P1")
+	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1)
+
+	PORT_MODIFY("P2")
+	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(2)
+
+	PORT_MODIFY("P3")
+	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(3)
+
+	PORT_MODIFY("P4")
+	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(4)
+INPUT_PORTS_END
+
 static INPUT_PORTS_START( zn4w )
 	PORT_INCLUDE( zn )
 
@@ -5111,8 +5127,8 @@ GAME( 1996, primrag2,  coh1000w, coh1000w,    primrag2, driver_device, 0, ROT0,
 
 /* Acclaim */
 GAME( 1995, coh1000a,  0,        coh1000a,    zn,       driver_device, 0, ROT0, "Acclaim", "Acclaim PSX", MACHINE_IS_BIOS_ROOT )
-GAME( 1996, nbajamex,  coh1000a, nbajamex,    zn,       zn_state, nbajamex, ROT0, "Acclaim", "NBA Jam Extreme (ver. 1.10I)", MACHINE_IMPERFECT_GRAPHICS )
-GAME( 1996, nbajamexa, nbajamex, nbajamex,    zn,       zn_state, nbajamex, ROT0, "Acclaim", "NBA Jam Extreme (ver. 1.04)", MACHINE_IMPERFECT_GRAPHICS )
+GAME( 1996, nbajamex,  coh1000a, nbajamex,    nbajamex, zn_state, nbajamex, ROT0, "Acclaim", "NBA Jam Extreme (ver. 1.10I)", MACHINE_IMPERFECT_GRAPHICS )
+GAME( 1996, nbajamexa, nbajamex, nbajamex,    nbajamex, zn_state, nbajamex, ROT0, "Acclaim", "NBA Jam Extreme (ver. 1.04)", MACHINE_IMPERFECT_GRAPHICS )
 GAME( 1996, jdredd,    coh1000a, jdredd,      jdredd,   driver_device, 0, ROT0, "Acclaim", "Judge Dredd (Rev C Dec. 17 1997)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND )
 GAME( 1996, jdreddb,   jdredd,   jdredd,      jdredd,   driver_device, 0, ROT0, "Acclaim", "Judge Dredd (Rev B Nov. 26 1997)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND )
 
diff --git a/src/mame/drivers/zwackery.cpp b/src/mame/drivers/zwackery.cpp
new file mode 100644
index 0000000..de221d8
--- /dev/null
+++ b/src/mame/drivers/zwackery.cpp
@@ -0,0 +1,609 @@
+// license: BSD-3-Clause
+// copyright-holders: Aaron Giles, Bryan McPhail
+/***************************************************************************
+
+    Zwackery
+
+    © 1984 Midway
+
+    The hardware consists of the following boards:
+    - Venus CPU (B084-91668-A385)
+    - Venus Video (B084-91675-A385)
+    - Venus Background (B084-91672-A385)
+    - Artificial Artist (B084-91671-A385)
+
+    TODO:
+    - Accurate screen timings
+
+***************************************************************************/
+
+#include "emu.h"
+#include "cpu/m68000/m68000.h"
+#include "machine/6821pia.h"
+#include "machine/6840ptm.h"
+#include "machine/watchdog.h"
+#include "audio/csd.h"
+
+
+//**************************************************************************
+//  TYPE DEFINITIONS
+//**************************************************************************
+
+class zwackery_state : public driver_device
+{
+public:
+	zwackery_state(const machine_config &mconfig, device_type type, const char *tag)
+		: driver_device(mconfig, type, tag),
+		m_maincpu(*this, "maincpu"),
+		m_pia0(*this, "pia0"),
+		m_pia1(*this, "pia1"),
+		m_pia2(*this, "pia2"),
+		m_ptm(*this, "ptm"),
+		m_watchdog(*this, "watchdog"),
+		m_screen(*this, "screen"),
+		m_gfxdecode(*this, "gfxdecode"),
+		m_videoram(*this, "videoram"),
+		m_cheap_squeak_deluxe(*this, "csd"),
+		m_bg_tilemap(nullptr),
+		m_fg_tilemap(nullptr)
+	{ }
+
+	DECLARE_VIDEO_START(zwackery);
+	TIMER_DEVICE_CALLBACK_MEMBER(scanline_cb);
+	DECLARE_WRITE16_MEMBER(videoram_w);
+	DECLARE_READ8_MEMBER(spriteram_r);
+	DECLARE_WRITE8_MEMBER(spriteram_w);
+	void update_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int priority);
+	uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
+	TILE_GET_INFO_MEMBER(get_bg_tile_info);
+	TILE_GET_INFO_MEMBER(get_fg_tile_info);
+
+	DECLARE_WRITE8_MEMBER(pia0_porta_w);
+	DECLARE_WRITE_LINE_MEMBER(pia0_irq_w);
+	DECLARE_READ8_MEMBER(pia1_porta_r);
+	DECLARE_WRITE8_MEMBER(pia1_porta_w);
+	DECLARE_READ8_MEMBER(pia1_portb_r);
+	DECLARE_READ8_MEMBER(pia2_porta_r);
+
+	DECLARE_READ8_MEMBER(ptm_r);
+
+protected:
+	virtual void machine_start() override;
+
+private:
+	required_device<m68000_device> m_maincpu;
+	required_device<pia6821_device> m_pia0;
+	required_device<pia6821_device> m_pia1;
+	required_device<pia6821_device> m_pia2;
+	required_device<ptm6840_device> m_ptm;
+	required_device<watchdog_timer_device> m_watchdog;
+	required_device<screen_device> m_screen;
+	required_device<gfxdecode_device> m_gfxdecode;
+	required_shared_ptr<uint16_t> m_videoram;
+	required_device<midway_cheap_squeak_deluxe_device> m_cheap_squeak_deluxe;
+
+	tilemap_t *m_bg_tilemap;
+	tilemap_t *m_fg_tilemap;
+
+	std::unique_ptr<uint8_t[]> m_spriteram;
+
+	std::unique_ptr<uint8_t[]> m_srcdata0;
+	std::unique_ptr<uint8_t[]> m_srcdata2;
+};
+
+
+//**************************************************************************
+//  ADDRESS MAPS
+//**************************************************************************
+
+static ADDRESS_MAP_START( zwackery_map, AS_PROGRAM, 16, zwackery_state )
+	ADDRESS_MAP_UNMAP_HIGH
+	AM_RANGE(0x000000, 0x037fff) AM_ROM
+	AM_RANGE(0x080000, 0x080fff) AM_RAM
+	AM_RANGE(0x084000, 0x084fff) AM_RAM
+	AM_RANGE(0x100000, 0x10000f) AM_READ8(ptm_r, 0xff00) AM_DEVWRITE8("ptm", ptm6840_device, write, 0xff00)
+	AM_RANGE(0x104000, 0x104007) AM_DEVREADWRITE8("pia0", pia6821_device, read, write, 0xff00)
+	AM_RANGE(0x108000, 0x108007) AM_DEVREADWRITE8("pia1", pia6821_device, read, write, 0x00ff)
+	AM_RANGE(0x10c000, 0x10c007) AM_DEVREADWRITE8("pia2", pia6821_device, read, write, 0x00ff)
+	AM_RANGE(0x800000, 0x800fff) AM_RAM_WRITE(videoram_w) AM_SHARE("videoram")
+	AM_RANGE(0x802000, 0x803fff) AM_RAM_DEVWRITE("palette", palette_device, write) AM_SHARE("palette")
+	AM_RANGE(0xc00000, 0xc00fff) AM_READWRITE8(spriteram_r, spriteram_w, 0x00ff)
+ADDRESS_MAP_END
+
+
+//**************************************************************************
+//  INPUTS
+//**************************************************************************
+
+static INPUT_PORTS_START( zwackery )
+	PORT_START("IN0")
+	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START1 )
+	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START2 )
+	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_COIN1 )
+	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_COIN2 )
+	PORT_SERVICE( 0x0010, IP_ACTIVE_LOW )
+	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_SERVICE1 )
+	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_TILT )
+	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("Sword")
+
+	PORT_START("IN1")
+	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT )  PORT_8WAY
+	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY
+	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN )  PORT_8WAY
+	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP )    PORT_8WAY
+	PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_SPECIAL )    // sound communications
+
+	PORT_START("IN2")
+	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("Spell Up")
+	PORT_BIT( 0x3e, IP_ACTIVE_HIGH, IPT_UNUSED ) // encoder wheel
+	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("Shield")
+	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("Spell Down")
+
+	PORT_START("IN3")
+	PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
+
+	PORT_START("DSW")
+	PORT_DIPNAME( 0x07, 0x00, DEF_STR( Coinage ) )     PORT_DIPLOCATION("SW1:1,2,3")
+	PORT_DIPSETTING(    0x05, DEF_STR( 6C_1C ) )
+	PORT_DIPSETTING(    0x04, DEF_STR( 5C_1C ) )
+	PORT_DIPSETTING(    0x03, DEF_STR( 4C_1C ) )
+	PORT_DIPSETTING(    0x02, DEF_STR( 3C_1C ) )
+	PORT_DIPSETTING(    0x01, DEF_STR( 2C_1C ) )
+	PORT_DIPSETTING(    0x00, DEF_STR( 1C_1C ) )
+	PORT_DIPSETTING(    0x06, DEF_STR( 1C_2C ) )
+	PORT_DIPSETTING(    0x07, DEF_STR( Free_Play ) )
+	PORT_DIPNAME( 0x38, 0x00, "Buy-in" )               PORT_DIPLOCATION("SW1:4,5,6")
+	PORT_DIPSETTING(    0x00, "1 coin" )
+	PORT_DIPSETTING(    0x08, "2 coins" )
+	PORT_DIPSETTING(    0x10, "3 coins" )
+	PORT_DIPSETTING(    0x18, "4 coins" )
+	PORT_DIPSETTING(    0x20, "5 coins" )
+	PORT_DIPSETTING(    0x28, "6 coins" )
+	PORT_DIPSETTING(    0x30, "7 coins" )
+	PORT_DIPSETTING(    0x38, DEF_STR( None ) )
+	PORT_DIPNAME( 0xc0, 0x00, DEF_STR( Difficulty ) )  PORT_DIPLOCATION("SW1:7,8")
+	PORT_DIPSETTING(    0xc0, DEF_STR( Easier ) )
+	PORT_DIPSETTING(    0x00, DEF_STR( Normal ) )
+	PORT_DIPSETTING(    0x40, DEF_STR( Harder ) )
+	PORT_DIPSETTING(    0x80, DEF_STR( Hardest ) )
+
+	PORT_START("IN5")
+	PORT_BIT( 0xff, 0x00, IPT_DIAL ) PORT_SENSITIVITY(50) PORT_KEYDELTA(10) PORT_CODE_DEC(KEYCODE_Z) PORT_CODE_INC(KEYCODE_X) PORT_REVERSE
+INPUT_PORTS_END
+
+
+//**************************************************************************
+//  VIDEO EMULATION
+//**************************************************************************
+
+VIDEO_START_MEMBER( zwackery_state, zwackery )
+{
+	const uint8_t *colordatabase = (const uint8_t *)memregion("bg_color")->base();
+	gfx_element *gfx0 = m_gfxdecode->gfx(0);
+	gfx_element *gfx2 = m_gfxdecode->gfx(2);
+
+	// initialize the background tilemap
+	m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(zwackery_state::get_bg_tile_info),this), TILEMAP_SCAN_ROWS,  16,16, 32,32);
+
+	// initialize the foreground tilemap
+	m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(zwackery_state::get_fg_tile_info),this), TILEMAP_SCAN_ROWS,  16,16, 32,32);
+	m_fg_tilemap->set_transparent_pen(0);
+
+	// allocate memory for the assembled gfx data
+	m_srcdata0 = std::make_unique<uint8_t[]>(gfx0->elements() * gfx0->width() * gfx0->height());
+	m_srcdata2 = std::make_unique<uint8_t[]>(gfx2->elements() * gfx2->width() * gfx2->height());
+
+	// "colorize" each code
+	uint8_t *dest0 = m_srcdata0.get();
+	uint8_t *dest2 = m_srcdata2.get();
+	for (int code = 0; code < gfx0->elements(); code++)
+	{
+		const uint8_t *coldata = colordatabase + code * 32;
+		const uint8_t *gfxdata0 = gfx0->get_data(code);
+		const uint8_t *gfxdata2 = gfx2->get_data(code);
+
+		// assume 16 rows
+		for (int y = 0; y < 16; y++)
+		{
+			const uint8_t *gd0 = gfxdata0;
+			const uint8_t *gd2 = gfxdata2;
+
+			// 16 columns
+			for (int x = 0; x < 16; x++, gd0++, gd2++)
+			{
+				int coloffs = (y & 0x0c) | ((x >> 2) & 0x03);
+				int pen0 = coldata[coloffs * 2 + 0];
+				int pen1 = coldata[coloffs * 2 + 1];
+				int tp0, tp1;
+
+				// every 4 pixels gets its own foreground/background colors
+				*dest0++ = *gd0 ? pen1 : pen0;
+
+				// for gfx 2, we convert all low-priority pens to 0
+				tp0 = (pen0 & 0x80) ? pen0 : 0;
+				tp1 = (pen1 & 0x80) ? pen1 : 0;
+				*dest2++ = *gd2 ? tp1 : tp0;
+			}
+
+			// advance
+			gfxdata0 += gfx0->rowbytes();
+			gfxdata2 += gfx2->rowbytes();
+		}
+	}
+
+	// make the assembled data our new source data
+	gfx0->set_raw_layout(m_srcdata0.get(), gfx0->width(), gfx0->height(), gfx0->elements(), 8 * gfx0->width(), 8 * gfx0->width() * gfx0->height());
+	gfx2->set_raw_layout(m_srcdata2.get(), gfx2->width(), gfx2->height(), gfx2->elements(), 8 * gfx2->width(), 8 * gfx2->width() * gfx2->height());
+}
+
+TIMER_DEVICE_CALLBACK_MEMBER( zwackery_state::scanline_cb )
+{
+	switch (param)
+	{
+	case 0:
+		// VSYNC
+		m_ptm->set_c1(0);
+		m_ptm->set_c1(1);
+		break;
+
+	case 474:
+		// source of this signal is pal.d3 (current value taken from original driver)
+		m_pia0->ca1_w(1);
+		break;
+
+	case 475:
+		// turn it off again after one scanline
+		m_pia0->ca1_w(0);
+		break;
+	}
+
+	// HSYNC
+	m_ptm->set_c3(0);
+	m_ptm->set_c3(1);
+}
+
+WRITE16_MEMBER( zwackery_state::videoram_w )
+{
+	COMBINE_DATA(&m_videoram[offset]);
+	m_bg_tilemap->mark_tile_dirty(offset);
+	m_fg_tilemap->mark_tile_dirty(offset);
+}
+
+READ8_MEMBER( zwackery_state::spriteram_r )
+{
+	return m_spriteram[offset];
+}
+
+WRITE8_MEMBER( zwackery_state::spriteram_w )
+{
+	m_spriteram[offset] = data;
+}
+
+void zwackery_state::update_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int priority)
+{
+	screen.priority().fill(1, cliprect);
+
+	// loop over sprite RAM
+	for (int offs = 0x800 - 4; offs >= 0; offs -= 4)
+	{
+		int code, color, flipx, flipy, x, y, flags;
+
+		// get the code and skip if zero
+		code = m_spriteram[offs + 2];
+		if (code == 0)
+			continue;
+
+		// extract the flag bits and determine the color
+		flags = m_spriteram[offs + 1];
+		color = ((~flags >> 2) & 0x0f) | ((flags & 0x02) << 3);
+
+		// for low priority, draw everything but color 7
+		if (!priority)
+		{
+			if (color == 7)
+				continue;
+		}
+
+		// for high priority, only draw color 7
+		else
+		{
+			if (color != 7)
+				continue;
+		}
+
+		// determine flipping and coordinates
+		flipx = ~flags & 0x40;
+		flipy = flags & 0x80;
+		x = (231 - m_spriteram[offs + 3]) * 2;
+		y = (241 - m_spriteram[offs]) * 2;
+
+		if (x <= -32) x += 512;
+
+		// sprites use color 0 for background pen and 8 for the 'under tile' pen.
+		// The color 8 is used to cover over other sprites.
+
+		// first draw the sprite, visible
+		m_gfxdecode->gfx(1)->prio_transmask(bitmap,cliprect, code, color, flipx, flipy, x, y,
+				screen.priority(), 0x00, 0x0101);
+
+		// then draw the mask, behind the background but obscuring following sprites
+		m_gfxdecode->gfx(1)->prio_transmask(bitmap,cliprect, code, color, flipx, flipy, x, y,
+				screen.priority(), 0x02, 0xfeff);
+	}
+}
+
+uint32_t zwackery_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
+{
+	// draw the background
+	m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
+
+	// draw the low-priority sprites
+	update_sprites(screen, bitmap, cliprect, 0);
+
+	// redraw tiles with priority over sprites
+	m_fg_tilemap->draw(screen, bitmap, cliprect, 1, 0);
+
+	// draw the high-priority sprites
+	update_sprites(screen, bitmap, cliprect, 1);
+
+	return 0;
+}
+
+TILE_GET_INFO_MEMBER( zwackery_state::get_bg_tile_info )
+{
+	uint16_t data = m_videoram[tile_index];
+	int color = (data >> 13) & 7;
+	SET_TILE_INFO_MEMBER(0, data & 0x3ff, color, TILE_FLIPYX(data >> 11));
+}
+
+TILE_GET_INFO_MEMBER( zwackery_state::get_fg_tile_info )
+{
+	uint16_t data = m_videoram[tile_index];
+	int color = (data >> 13) & 7;
+	SET_TILE_INFO_MEMBER(2, data & 0x3ff, color, TILE_FLIPYX(data >> 11));
+	tileinfo.category = (color != 0);
+}
+
+static const gfx_layout zwackery_layout =
+{
+	16,16,
+	RGN_FRAC(1,2),
+	8,
+	{ 0, 0, 0, 0, 0, 0, 0, 0 },
+	{ STEP4(3,-1), STEP4(11,-1), STEP4(19,-1), STEP4(27,-1) },
+	{ 4, RGN_FRAC(1,2)+4, 0, RGN_FRAC(1,2)+0, 36, RGN_FRAC(1,2)+36, 32, RGN_FRAC(1,2)+32,
+		68, RGN_FRAC(1,2)+68, 64, RGN_FRAC(1,2)+64, 100, RGN_FRAC(1,2)+100, 96, RGN_FRAC(1,2)+96 },
+	128
+};
+
+static const gfx_layout mcr68_sprite_layout =
+{
+	32,32,
+	RGN_FRAC(1,4),
+	4,
+	{ STEP4(0,1) },
+	{ STEP2(RGN_FRAC(0,4)+0,4), STEP2(RGN_FRAC(1,4)+0,4), STEP2(RGN_FRAC(2,4)+0,4), STEP2(RGN_FRAC(3,4)+0,4),
+		STEP2(RGN_FRAC(0,4)+8,4), STEP2(RGN_FRAC(1,4)+8,4), STEP2(RGN_FRAC(2,4)+8,4), STEP2(RGN_FRAC(3,4)+8,4),
+		STEP2(RGN_FRAC(0,4)+16,4), STEP2(RGN_FRAC(1,4)+16,4), STEP2(RGN_FRAC(2,4)+16,4), STEP2(RGN_FRAC(3,4)+16,4),
+		STEP2(RGN_FRAC(0,4)+24,4), STEP2(RGN_FRAC(1,4)+24,4), STEP2(RGN_FRAC(2,4)+24,4), STEP2(RGN_FRAC(3,4)+24,4) },
+	{ STEP32(0,32) },
+	32*32
+};
+
+static GFXDECODE_START( zwackery )
+	GFXDECODE_ENTRY( "gfx1",    0, zwackery_layout,     0,     16 )
+	GFXDECODE_ENTRY( "sprites", 0, mcr68_sprite_layout, 0x800, 32 )
+	GFXDECODE_ENTRY( "gfx1",    0, zwackery_layout,     0,     16 )  // yes, an extra copy
+GFXDECODE_END
+
+
+//**************************************************************************
+//  AUDIO
+//**************************************************************************
+
+WRITE8_MEMBER( zwackery_state::pia1_porta_w )
+{
+	m_cheap_squeak_deluxe->sr_w(space, 0, data >> 4);
+}
+
+
+//**************************************************************************
+//  INPUTS/OUTPUTS
+//**************************************************************************
+
+WRITE8_MEMBER( zwackery_state::pia0_porta_w )
+{
+	// bits 0, 1 and 2 control meters?
+	// bits 3 and 4 control coin counters?
+	// bits 5 and 6 control hflip/vflip
+
+	// bit 7, watchdog
+	if (BIT(data, 7) == 0)
+		m_watchdog->watchdog_reset();
+}
+
+WRITE_LINE_MEMBER(zwackery_state::pia0_irq_w)
+{
+	int irq_state = m_pia0->irq_a_state() | m_pia0->irq_b_state();
+	m_maincpu->set_input_line(5, irq_state ? ASSERT_LINE : CLEAR_LINE);
+}
+
+READ8_MEMBER( zwackery_state::pia1_porta_r )
+{
+	uint8_t data = ioport("IN1")->read();
+	m_pia1->set_port_a_z_mask(data);
+
+	return data;
+}
+
+READ8_MEMBER( zwackery_state::pia1_portb_r )
+{
+	uint8_t result = ioport("IN2")->read();
+	uint8_t wheel = ioport("IN5")->read();
+
+	return result | ((wheel >> 2) & 0x3e);
+}
+
+READ8_MEMBER( zwackery_state::pia2_porta_r )
+{
+	uint8_t data = ioport("IN3")->read();
+	m_pia2->set_port_a_z_mask(data);
+
+	return data;
+}
+
+
+//**************************************************************************
+//  MACHINE EMULATION
+//**************************************************************************
+
+// Zwackery does a timer test:
+// It loads $1388 into one of the timers clocked by E
+// Then it sits in a tight loop counting down from $4E4
+//       BTST #$1,($2,A0)
+//       DBNE D1,*-6
+// It expects D1 to end up between 0 and 5; in order to
+// make this happen, we must assume that reads from the
+// 6840 take 14 additional cycles
+READ8_MEMBER( zwackery_state::ptm_r )
+{
+	space.device().execute().adjust_icount(-14);
+	return m_ptm->read(space, offset);
+}
+
+void zwackery_state::machine_start()
+{
+	// allocate 8-bit spriteram
+	m_spriteram = std::make_unique<uint8_t[]>(0x800);
+
+	// register for save states
+	save_pointer(NAME(m_spriteram.get()), 0x800);
+}
+
+
+//**************************************************************************
+//  MACHINE DEFINTIONS
+//**************************************************************************
+
+static MACHINE_CONFIG_START( zwackery, zwackery_state )
+	// basic machine hardware
+	MCFG_CPU_ADD("maincpu", M68000, 7652400)    // based on counter usage, should be XTAL_16MHz/2
+	MCFG_CPU_PROGRAM_MAP(zwackery_map)
+
+	MCFG_QUANTUM_PERFECT_CPU("maincpu")
+
+	MCFG_WATCHDOG_ADD("watchdog")
+
+	MCFG_DEVICE_ADD("ptm", PTM6840, 7652400 / 10)
+	MCFG_PTM6840_IRQ_CB(INPUTLINE("maincpu", 6))
+
+	MCFG_DEVICE_ADD("pia0", PIA6821, 0)
+	MCFG_PIA_READPB_HANDLER(IOPORT("IN0"))
+	MCFG_PIA_WRITEPA_HANDLER(WRITE8(zwackery_state, pia0_porta_w))
+	MCFG_PIA_IRQA_HANDLER(WRITELINE(zwackery_state, pia0_irq_w))
+	MCFG_PIA_IRQB_HANDLER(WRITELINE(zwackery_state, pia0_irq_w))
+
+	MCFG_DEVICE_ADD("pia1", PIA6821, 0)
+	MCFG_PIA_READPA_HANDLER(READ8(zwackery_state, pia1_porta_r))
+	MCFG_PIA_WRITEPA_HANDLER(WRITE8(zwackery_state, pia1_porta_w))
+	MCFG_PIA_READPB_HANDLER(READ8(zwackery_state, pia1_portb_r))
+	MCFG_PIA_CA2_HANDLER(DEVWRITELINE("csd", midway_cheap_squeak_deluxe_device, sirq_w))
+
+	MCFG_DEVICE_ADD("pia2", PIA6821, 0)
+	MCFG_PIA_READPA_HANDLER(READ8(zwackery_state, pia2_porta_r))
+	MCFG_PIA_READPB_HANDLER(IOPORT("DSW"))
+
+	// video hardware
+	MCFG_SCREEN_ADD("screen", RASTER)
+	MCFG_SCREEN_REFRESH_RATE(30)
+	MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) // not accurate
+	MCFG_SCREEN_SIZE(32*16, 30*16)
+	MCFG_SCREEN_VISIBLE_AREA(0, 32*16-1, 0, 30*16-1)
+	MCFG_SCREEN_UPDATE_DRIVER(zwackery_state, screen_update)
+	MCFG_SCREEN_PALETTE("palette")
+
+	MCFG_TIMER_DRIVER_ADD_SCANLINE("scantimer", zwackery_state, scanline_cb, "screen", 0, 1)
+
+	MCFG_GFXDECODE_ADD("gfxdecode", "palette", zwackery)
+	MCFG_PALETTE_ADD("palette", 4096)
+	MCFG_PALETTE_FORMAT(xRRRRRBBBBBGGGGG_inverted)
+
+	MCFG_VIDEO_START_OVERRIDE(zwackery_state, zwackery)
+
+	// sound hardware
+	MCFG_SPEAKER_STANDARD_MONO("speaker")
+	MCFG_SOUND_ADD("csd", MIDWAY_CHEAP_SQUEAK_DELUXE, 0)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "speaker", 1.0)
+MACHINE_CONFIG_END
+
+
+//**************************************************************************
+//  ROM DEFINITIONS
+//**************************************************************************
+
+ROM_START( zwackery )
+	ROM_REGION(0x40000, "maincpu", 0)
+	ROM_LOAD16_BYTE("385a-42aae-jxrd.a6",  0x00000, 0x4000, CRC(6fb9731c) SHA1(ee5b297ef2b4cf20df5e776f1c585b51f174bfa7))
+	ROM_LOAD16_BYTE("385a-42aae-kxrd.b6",  0x00001, 0x4000, CRC(84b92555) SHA1(9b4af81374828c1742c1e13fc425eea2973b0867))
+	ROM_LOAD16_BYTE("385a-42aae-lxrd.a7",  0x08000, 0x4000, CRC(e6977a2a) SHA1(602bf3f7e0f4080cb5b72d8fd3ee9fd11f27c558))
+	ROM_LOAD16_BYTE("385a-42aae-mxrd.b7",  0x08001, 0x4000, CRC(f5d0a60e) SHA1(7e0e4936cb37ac16d6db5533ae4aecdfb07ead93))
+	ROM_LOAD16_BYTE("385a-42aae-nxrd.a8",  0x10000, 0x4000, CRC(ec5841d9) SHA1(4bafe614e8993994b0ea9aedc8dc2474361e4594))
+	ROM_LOAD16_BYTE("385a-42aae-pxrd.b8",  0x10001, 0x4000, CRC(d7d99ce0) SHA1(fdf428ab9c96dae555d49bac47495613ba265452))
+	ROM_LOAD16_BYTE("385a-42aae-rxrd.a9",  0x18000, 0x4000, CRC(b9fe7bf5) SHA1(a94f80f49b4520a2c1098eee8983560b4ecdf3d5))
+	ROM_LOAD16_BYTE("385a-42aae-txrd.b9",  0x18001, 0x4000, CRC(5e261b3b) SHA1(dcf99f528c9e3b4f8b52d413c088559bfb37d733))
+	ROM_LOAD16_BYTE("385a-42aae-uxrd.a10", 0x20000, 0x4000, CRC(55e380a5) SHA1(e3fef8486858cd714086449327a93b4a70ae73ff))
+	ROM_LOAD16_BYTE("385a-42aae-vxrd.b10", 0x20001, 0x4000, CRC(12249dca) SHA1(154170286047ea78645d45dfdd895a597dad17da))
+	ROM_LOAD16_BYTE("385a-42aae-wxrd.a11", 0x28000, 0x4000, CRC(6a39a8ca) SHA1(8ac9c3e60dc6f1918bfb95acf3ee170cedfb20ea))
+	ROM_LOAD16_BYTE("385a-42aae-yxrd.b11", 0x28001, 0x4000, CRC(ad6b45bc) SHA1(118496e898654b028f008a3d493e693ba000ef38))
+	ROM_LOAD16_BYTE("385a-42aae-zxrd.a12", 0x30000, 0x4000, CRC(e2d25e1f) SHA1(5d8ff303441eccf431422b453a173983a4513630))
+	ROM_LOAD16_BYTE("385a-42aae-1xrd.b12", 0x30001, 0x4000, CRC(e131f9b8) SHA1(08b131f2acc84d4c2c931bfd24e7de3d92a8a817))
+
+	ROM_REGION(0x8000, "csd:cpu", 0)
+	ROM_LOAD16_BYTE("385a-22aae-aamd.u7",  0x0000, 0x2000, CRC(5501f54b) SHA1(84c0851fb868e81400cfe3ebfd7b91fe98a47bac))
+	ROM_LOAD16_BYTE("385a-22aae-bamd.u17", 0x0001, 0x2000, CRC(2e482580) SHA1(92bd3e64ff580800ee16579d97bcb8b3bd9f755c))
+	ROM_LOAD16_BYTE("385a-22aae-camd.u8",  0x4000, 0x2000, CRC(13366575) SHA1(bcf25a7d4c6b2ccd7cd9978edafc66ef0cadfe72))
+	ROM_LOAD16_BYTE("385a-22aae-damd.u18", 0x4001, 0x2000, CRC(bcfe5820) SHA1(ca32daa645851a2373b3cdb8a5e63ebda84aa762))
+
+	ROM_REGION(0x8000, "gfx1", ROMREGION_INVERT)
+	ROM_LOAD("385a-42aae-2xrd.1h", 0x0000, 0x4000, CRC(a7237eb1) SHA1(197e5838ac2bc732ae9eb33a9257b9391d50abf8))
+	ROM_LOAD("385a-42aae-3xrd.1g", 0x4000, 0x4000, CRC(626cc69b) SHA1(86142bafa78f45d1a0bed0b83f3558b21384fa1a))
+
+	ROM_REGION(0x20000, "sprites", 0)
+	ROM_LOAD("385a-42aae-axrd.6h",  0x00000, 0x4000, CRC(a51158dc) SHA1(8d3b0054950443fdf57f83dcb973d05f6c7ad9c8))
+	ROM_LOAD("385a-42aae-exrd.7h",  0x04000, 0x4000, CRC(941feecf) SHA1(8e88c956332e78dc7e55139879f2272116415714))
+	ROM_LOAD("385a-42aae-bxrd.6j",  0x08000, 0x4000, CRC(f3eef316) SHA1(026e18bdfdda8cc9d0774e6d9d758686bf16992c))
+	ROM_LOAD("385a-42aae-fxrd.7j",  0x0c000, 0x4000, CRC(a8a34033) SHA1(abd9fde84bb079c84126ad04d584ec03b44b60cd))
+	ROM_LOAD("385a-42aae-cxrd.10h", 0x10000, 0x4000, CRC(a99daea6) SHA1(c323e05f398b7e9e04b75fd8ac5e8ab675236d66))
+	ROM_LOAD("385a-42aae-gxrd.11h", 0x14000, 0x4000, CRC(c1a767fb) SHA1(c16e09b39b09d409b534ce4c53366e43237a3759))
+	ROM_LOAD("385a-42aae-dxrd.10j", 0x18000, 0x4000, CRC(4dd04376) SHA1(069b64397e7a961c1fc246671472f759bd9f6c03))
+	ROM_LOAD("385a-42aae-hxrd.11j", 0x1c000, 0x4000, CRC(e8c6a880) SHA1(dd3d52ddbc36e244b96cfb87e6a80adb94626407))
+
+	ROM_REGION( 0x8000, "bg_color", 0 )
+	ROM_LOAD16_BYTE("385a-42aae-5xrd.1f", 0x0000, 0x4000, CRC(a0dfcd7e) SHA1(0fc6723eddef2a96de9bf1f48006dd067c148540))
+	ROM_LOAD16_BYTE("385a-42aae-4xrd.1e", 0x0001, 0x4000, CRC(ab504dc8) SHA1(4ebdcd42624e94c29ccdb8247bfff2d8e936ddd7))
+
+	ROM_REGION( 0x000c, "plds", 0 )
+	// located on the "Venus CPU" board
+	ROM_LOAD( "pal.d5",    0x0000, 0x00001, NO_DUMP ) // H-T
+	ROM_LOAD( "pal.d2",    0x0001, 0x00001, NO_DUMP ) // V-T
+	ROM_LOAD( "pal.d4",    0x0002, 0x00001, NO_DUMP ) // MISC V&H PAL
+	ROM_LOAD( "pal.d3",    0x0003, 0x00001, NO_DUMP ) // MISC CUSTOM PAL
+	ROM_LOAD( "pal.e6",    0x0004, 0x00001, NO_DUMP ) // CPU WTS PAL
+	ROM_LOAD( "pal.f8",    0x0005, 0x00001, NO_DUMP ) // CPU IOC PAL
+	ROM_LOAD( "pal.a5",    0x0006, 0x00001, NO_DUMP ) // CPU RMD PAL
+	// located on the "Venus VIDEO" board
+	ROM_LOAD( "pal.1f",    0x0007, 0x00001, NO_DUMP ) // PAL FGBDCD
+	ROM_LOAD( "pal.1d",    0x0008, 0x00001, NO_DUMP ) // PAL HCT
+	// located on the "Venus BACKGROUND" board
+	ROM_LOAD( "pal.1c",    0x0009, 0x00001, NO_DUMP ) // BGBPE PAL
+	ROM_LOAD( "pal.5c",    0x000a, 0x00001, NO_DUMP ) // HCT PAL
+	ROM_LOAD( "pal.5j",    0x000b, 0x00001, NO_DUMP ) // BGBDCD PAL
+ROM_END
+
+
+//**************************************************************************
+//  SYSTEM DRIVERS
+//**************************************************************************
+
+//    YEAR  NAME      PARENT  MACHINE   INPUT     CLASS          INIT  ROTATION  COMPANY         FULLNAME    FLAGS
+GAME( 1984, zwackery, 0,      zwackery, zwackery, driver_device, 0,    ROT0,     "Bally Midway", "Zwackery", MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/drivers/zx.cpp b/src/mame/drivers/zx.cpp
index 86671e6..cf2096e 100644
--- a/src/mame/drivers/zx.cpp
+++ b/src/mame/drivers/zx.cpp
@@ -473,13 +473,13 @@ ROM_END
 
 /* Game Drivers */
 
-COMP( 1980, zx80,       0,      0,      zx80,       zx80,    zx_state,    zx,     "Sinclair Research Ltd",    "ZX-80",               MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
-COMP( 1981, zx81,       0,      0,      zx81,       zx81,    zx_state,    zx,     "Sinclair Research Ltd",    "ZX-81",               MACHINE_NO_SOUND )
-COMP( 1982, ts1000,     zx81,   0,      ts1000,     zx81,    zx_state,    zx,     "Timex Sinclair",           "Timex Sinclair 1000", MACHINE_NO_SOUND )
-COMP( 1983, ts1500,     zx81,   0,      ts1500,     zx81,    zx_state,    zx,     "Timex Sinclair",           "Timex Sinclair 1500", MACHINE_NO_SOUND )
-COMP( 1983, tk85,       zx81,   0,      ts1000,     zx81,    zx_state,    zx,     "Microdigital",             "TK85",                MACHINE_NO_SOUND )
-COMP( 1983, ringo470,   zx81,   0,      ts1000,     zx81,    zx_state,    zx,     "Ritas do Brasil Ltda",     "Ringo 470",           MACHINE_NO_SOUND )
+COMP( 1980, zx80,       0,      0,      zx80,       zx80,    zx_state,    zx,     "Sinclair Research Ltd",    "ZX-80",               MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW )
+COMP( 1981, zx81,       0,      0,      zx81,       zx81,    zx_state,    zx,     "Sinclair Research Ltd",    "ZX-81",               MACHINE_NO_SOUND_HW )
+COMP( 1982, ts1000,     zx81,   0,      ts1000,     zx81,    zx_state,    zx,     "Timex Sinclair",           "Timex Sinclair 1000", MACHINE_NO_SOUND_HW )
+COMP( 1983, ts1500,     zx81,   0,      ts1500,     zx81,    zx_state,    zx,     "Timex Sinclair",           "Timex Sinclair 1500", MACHINE_NO_SOUND_HW )
+COMP( 1983, tk85,       zx81,   0,      ts1000,     zx81,    zx_state,    zx,     "Microdigital",             "TK85",                MACHINE_NO_SOUND_HW )
+COMP( 1983, ringo470,   zx81,   0,      ts1000,     zx81,    zx_state,    zx,     "Ritas do Brasil Ltda",     "Ringo 470",           MACHINE_NO_SOUND_HW )
 COMP( 1984, pc8300,     zx81,   0,      pc8300,     pc8300,  zx_state,    zx,     "Your Computer",            "PC8300",              MACHINE_NOT_WORKING )
 COMP( 1983, pow3000,    zx81,   0,      pow3000,    pow3000, zx_state,    zx,     "Creon Enterprises",        "Power 3000",          MACHINE_NOT_WORKING )
 COMP( 1982, lambda,     zx81,   0,      pow3000,    pow3000, zx_state,    zx,     "Lambda Electronics Ltd",   "Lambda 8300",         MACHINE_NOT_WORKING )
-COMP( 1997, zx97,       zx81,   0,      zx81,       zx81,    zx_state,    zx,     "Wilf Rigter",              "ZX97", MACHINE_NOT_WORKING | MACHINE_NO_SOUND | MACHINE_UNOFFICIAL )
+COMP( 1997, zx97,       zx81,   0,      zx81,       zx81,    zx_state,    zx,     "Wilf Rigter",              "ZX97", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW | MACHINE_UNOFFICIAL )
diff --git a/src/mame/includes/4enraya.h b/src/mame/includes/4enraya.h
index 9d2fcb0..69aac58 100644
--- a/src/mame/includes/4enraya.h
+++ b/src/mame/includes/4enraya.h
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina, Roberto Fresca
 /*************************************************************************
 
diff --git a/src/mame/includes/amiga.h b/src/mame/includes/amiga.h
index 25dc743..5a01964 100644
--- a/src/mame/includes/amiga.h
+++ b/src/mame/includes/amiga.h
@@ -504,6 +504,8 @@ public:
 		custom_chip_w(m_maincpu->space(AS_PROGRAM), offset, data, mem_mask);
 	}
 
+	void blitter_setup();
+
 protected:
 	// agnus/alice chip id
 	enum
@@ -660,7 +662,7 @@ private:
 
 	void serial_adjust();
 	void serial_shift();
-	void rx_write(amiga_state *state, int level);
+	void rx_write(int level);
 
 	uint32_t amiga_gethvpos();
 };
diff --git a/src/mame/includes/archimds.h b/src/mame/includes/archimds.h
index bea394d..168d1b7 100644
--- a/src/mame/includes/archimds.h
+++ b/src/mame/includes/archimds.h
@@ -91,6 +91,7 @@ public:
 	uint8_t m_ioc_regs[0x80/4];
 	uint8_t m_vidc_bpp_mode;
 	uint8_t m_vidc_interlace;
+	uint16_t m_vidc_vblank_time;
 
 	uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
 	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
@@ -130,7 +131,7 @@ private:
 	int m_memc_latchrom;
 	uint32_t m_ioc_timercnt[4], m_ioc_timerout[4];
 	uint32_t m_vidc_vidstart, m_vidc_vidend, m_vidc_vidinit, m_vidc_vidcur,m_vidc_cinit;
-	uint32_t m_vidc_sndstart, m_vidc_sndend, m_vidc_sndcur;
+	uint32_t m_vidc_sndstart, m_vidc_sndend, m_vidc_sndcur, m_vidc_sndendcur;
 	uint8_t m_video_dma_on,m_audio_dma_on;
 	uint8_t m_vidc_pixel_clk;
 	uint8_t m_vidc_stereo_reg[8];
diff --git a/src/mame/includes/astrocde.h b/src/mame/includes/astrocde.h
index 25b4861..74cfd06 100644
--- a/src/mame/includes/astrocde.h
+++ b/src/mame/includes/astrocde.h
@@ -19,8 +19,6 @@
 #define AC_STARS            (0x04)
 #define AC_MONITOR_BW       (0x08)
 
-#define USE_FAKE_VOTRAX     (1)
-
 
 class astrocde_state : public driver_device
 {
@@ -195,13 +193,8 @@ public:
 	void init_sparklestar();
 	virtual void machine_start() override;
 
-	/*----------- defined in audio/wow.c -----------*/
-	DECLARE_READ8_MEMBER( wow_speech_r );
-	CUSTOM_INPUT_MEMBER( wow_speech_status_r );
-
-	/*----------- defined in audio/gorf.c -----------*/
-	DECLARE_READ8_MEMBER( gorf_speech_r );
-	CUSTOM_INPUT_MEMBER( gorf_speech_status_r );
+	DECLARE_READ8_MEMBER( votrax_speech_r );
+	CUSTOM_INPUT_MEMBER( votrax_speech_status_r );
 
 protected:
 	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
diff --git a/src/mame/includes/aussiebyte.h b/src/mame/includes/aussiebyte.h
index 39b9236..0ec8c3c 100644
--- a/src/mame/includes/aussiebyte.h
+++ b/src/mame/includes/aussiebyte.h
@@ -49,6 +49,7 @@ public:
 		, m_crtc(*this, "crtc")
 		, m_speaker(*this, "speaker")
 		, m_votrax(*this, "votrax")
+		, m_rtc(*this, "rtc")
 	{}
 
 	DECLARE_READ8_MEMBER(memory_read_byte);
@@ -71,6 +72,8 @@ public:
 	DECLARE_WRITE8_MEMBER(port35_w);
 	DECLARE_READ8_MEMBER(port36_r);
 	DECLARE_READ8_MEMBER(port37_r);
+	DECLARE_READ8_MEMBER(rtc_r);
+	DECLARE_WRITE8_MEMBER(rtc_w);
 	DECLARE_WRITE_LINE_MEMBER(fdc_intrq_w);
 	DECLARE_WRITE_LINE_MEMBER(fdc_drq_w);
 	DECLARE_WRITE_LINE_MEMBER(busreq_w);
@@ -124,4 +127,5 @@ private:
 	required_device<mc6845_device> m_crtc;
 	required_device<speaker_sound_device> m_speaker;
 	required_device<votrax_sc01_device> m_votrax;
+	required_device<msm5832_device> m_rtc;
 };
diff --git a/src/mame/includes/beezer.h b/src/mame/includes/beezer.h
deleted file mode 100644
index 4ed0eb3..0000000
--- a/src/mame/includes/beezer.h
+++ /dev/null
@@ -1,123 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Mathis Rosenhauer
-#include "machine/6522via.h"
-#include "cpu/m6809/m6809.h"
-#include "machine/watchdog.h"
-
-class beezer_sound_device;
-
-class beezer_state : public driver_device
-{
-public:
-	beezer_state(const machine_config &mconfig, device_type type, const char *tag)
-		: driver_device(mconfig, type, tag),
-		m_videoram(*this, "videoram"),
-		m_maincpu(*this, "maincpu"),
-		m_audiocpu(*this, "audiocpu"),
-		m_watchdog(*this, "watchdog"),
-		m_custom(*this, "custom"),
-		m_screen(*this, "screen"),
-		m_palette(*this, "palette") { }
-
-	required_shared_ptr<uint8_t> m_videoram;
-	int m_pbus;
-	int m_banklatch;
-
-	required_device<cpu_device> m_maincpu;
-	required_device<cpu_device> m_audiocpu;
-	required_device<watchdog_timer_device> m_watchdog;
-	required_device<beezer_sound_device> m_custom;
-	required_device<screen_device> m_screen;
-	required_device<palette_device> m_palette;
-
-	DECLARE_WRITE8_MEMBER(beezer_bankswitch_w);
-	DECLARE_WRITE8_MEMBER(beezer_map_w);
-	DECLARE_READ8_MEMBER(beezer_line_r);
-	DECLARE_DRIVER_INIT(beezer);
-	virtual void machine_start() override;
-	uint32_t screen_update_beezer(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
-	TIMER_DEVICE_CALLBACK_MEMBER(beezer_interrupt);
-	DECLARE_READ8_MEMBER(b_via_0_pa_r);
-	DECLARE_READ8_MEMBER(b_via_0_pb_r);
-	DECLARE_WRITE8_MEMBER(b_via_0_pa_w);
-	DECLARE_WRITE8_MEMBER(b_via_0_pb_w);
-	DECLARE_READ8_MEMBER(b_via_1_pa_r);
-	DECLARE_READ8_MEMBER(b_via_1_pb_r);
-	DECLARE_WRITE8_MEMBER(b_via_1_pa_w);
-	DECLARE_WRITE8_MEMBER(b_via_1_pb_w);
-};
-
-/*----------- defined in audio/beezer.c -----------*/
-
-/* 6840 variables */
-struct sh6840_timer_channel_beez
-{
-	uint8_t   cr;
-	uint8_t   state;
-	uint8_t   leftovers;
-	uint16_t  timer;
-	uint32_t  clocks;
-	uint8_t   int_flag;
-	union
-	{
-#ifdef LSB_FIRST
-		struct { uint8_t l, h; } b;
-#else
-		struct { uint8_t h, l; } b;
-#endif
-		uint16_t w;
-	} counter;
-};
-
-class beezer_sound_device : public device_t,
-									public device_sound_interface
-{
-public:
-	beezer_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-	~beezer_sound_device() {}
-
-	DECLARE_READ8_MEMBER( sh6840_r );
-	DECLARE_WRITE8_MEMBER( sh6840_w );
-	DECLARE_WRITE8_MEMBER( sfxctrl_w );
-	DECLARE_WRITE8_MEMBER( timer1_w );
-	DECLARE_READ8_MEMBER( noise_r );
-
-	//DECLARE_WRITE_LINE_MEMBER( update_irq_state );
-
-protected:
-	// device-level overrides
-	virtual void device_config_complete() override;
-	virtual void device_start() override;
-	virtual void device_reset() override;
-
-	// sound stream update overrides
-	virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
-private:
-	// internal state
-	cpu_device *m_maincpu;
-
-	/* IRQ variable */
-	//uint8_t m_ptm_irq_state;
-
-	struct sh6840_timer_channel_beez m_sh6840_timer[3];
-	uint8_t m_sh6840_volume[4];
-	uint8_t m_sh6840_MSB_latch;
-	uint8_t m_sh6840_LSB_latch;
-	uint32_t m_sh6840_LFSR;
-	uint32_t m_sh6840_LFSR_clocks;
-	uint32_t m_sh6840_clocks_per_sample;
-	uint32_t m_sh6840_clock_count;
-
-	uint32_t m_sh6840_latchwrite;
-	uint32_t m_sh6840_latchwriteold;
-	uint32_t m_sh6840_noiselatch1;
-	uint32_t m_sh6840_noiselatch3;
-
-	/* sound streaming variables */
-	sound_stream *m_stream;
-	//double m_freq_to_step;
-
-	int sh6840_update_noise(int clocks);
-};
-
-extern const device_type BEEZER;
diff --git a/src/mame/includes/bublbobl.h b/src/mame/includes/bublbobl.h
index c380a5c..26168ac 100644
--- a/src/mame/includes/bublbobl.h
+++ b/src/mame/includes/bublbobl.h
@@ -17,13 +17,21 @@ public:
 		m_videoram(*this, "videoram"),
 		m_objectram(*this, "objectram"),
 		m_mcu_sharedram(*this, "mcu_sharedram"),
+		m_mcu_sent(false),
+		m_main_sent(false),
+		m_from_main(0),
+		m_from_mcu(0),
+		m_from_mcu_latch(0),
+		m_to_mcu_latch(0),
+		m_old_portB(0),
 		m_maincpu(*this, "maincpu"),
 		m_mcu(*this, "mcu"),
 		m_audiocpu(*this, "audiocpu"),
 		m_slave(*this, "slave"),
 		m_gfxdecode(*this, "gfxdecode"),
 		m_palette(*this, "palette"),
-		m_soundlatch(*this, "soundlatch") { }
+		m_soundlatch(*this, "soundlatch")
+	{ }
 
 	/* memory pointers */
 	required_shared_ptr<uint8_t> m_videoram;
@@ -39,8 +47,7 @@ public:
 	int      m_sound_status;
 
 	/* mcu-related */
-	/* Tokio*/
-	int      m_tokio_prot_count;
+
 	/* Bubble Bobble MCU */
 	uint8_t    m_ddr1;
 	uint8_t    m_ddr2;
@@ -66,6 +73,14 @@ public:
 	/* Bobble Bobble */
 	int      m_ic43_a;
 	int      m_ic43_b;
+	/* Tokio */
+	bool m_mcu_sent;
+	bool m_main_sent;
+	uint8_t m_from_main;
+	uint8_t m_from_mcu;
+	uint8_t m_from_mcu_latch;
+	uint8_t m_to_mcu_latch;
+	uint8_t m_old_portB;
 
 	/* devices */
 	required_device<cpu_device> m_maincpu;
@@ -81,6 +96,8 @@ public:
 	DECLARE_WRITE8_MEMBER(tokio_videoctrl_w);
 	DECLARE_WRITE8_MEMBER(bublbobl_nmitrigger_w);
 	DECLARE_READ8_MEMBER(tokio_mcu_r);
+	DECLARE_WRITE8_MEMBER(tokio_mcu_w);
+
 	DECLARE_READ8_MEMBER(tokiob_mcu_r);
 	DECLARE_WRITE8_MEMBER(bublbobl_sound_command_w);
 	DECLARE_WRITE8_MEMBER(bublbobl_sh_nmi_disable_w);
@@ -114,6 +131,20 @@ public:
 	DECLARE_READ8_MEMBER(bublbobl_68705_port_b_r);
 	DECLARE_WRITE8_MEMBER(bublbobl_68705_port_b_w);
 	DECLARE_WRITE8_MEMBER(bublbobl_68705_ddr_b_w);
+
+
+
+
+	DECLARE_CUSTOM_INPUT_MEMBER(tokio_mcu_sent_r);
+	DECLARE_CUSTOM_INPUT_MEMBER(tokio_main_sent_r);
+
+
+	DECLARE_READ8_MEMBER(tokio_mcu_porta_r);
+	DECLARE_READ8_MEMBER(tokio_mcu_portc_r);
+	DECLARE_WRITE8_MEMBER(tokio_mcu_porta_w);
+	DECLARE_WRITE8_MEMBER(tokio_mcu_portb_w);
+
+
 	DECLARE_DRIVER_INIT(tokiob);
 	DECLARE_DRIVER_INIT(tokio);
 	DECLARE_DRIVER_INIT(dland);
diff --git a/src/mame/includes/dec0.h b/src/mame/includes/dec0.h
index b6fe6f8..fd03153 100644
--- a/src/mame/includes/dec0.h
+++ b/src/mame/includes/dec0.h
@@ -1,5 +1,6 @@
 // license:BSD-3-Clause
 // copyright-holders:Bryan McPhail
+#include "machine/74157.h"
 #include "machine/bankdev.h"
 #include "machine/gen_latch.h"
 #include "video/decbac06.h"
@@ -15,7 +16,6 @@ public:
 		m_audiocpu(*this, "audiocpu"),
 		m_subcpu(*this, "sub"),
 		m_mcu(*this, "mcu"),
-		m_msm(*this, "msm"),
 		m_palette(*this, "palette"),
 		m_tilegen1(*this, "tilegen1"),
 		m_tilegen2(*this, "tilegen2"),
@@ -33,7 +33,6 @@ public:
 	required_device<cpu_device> m_audiocpu;
 	optional_device<cpu_device> m_subcpu;
 	optional_device<cpu_device> m_mcu;
-	optional_device<msm5205_device> m_msm;
 	required_device<palette_device> m_palette;
 	optional_device<deco_bac06_device> m_tilegen1;
 	optional_device<deco_bac06_device> m_tilegen2;
@@ -115,22 +114,37 @@ class dec0_automat_state : public dec0_state
 {
 public:
 	dec0_automat_state(const machine_config &mconfig, device_type type, const char *tag)
-		: dec0_state(mconfig, type, tag) {
+		: dec0_state(mconfig, type, tag),
+		m_msm1(*this, "msm1"),
+		m_msm2(*this, "msm2"),
+		m_adpcm_select1(*this, "adpcm_select1"),
+		m_adpcm_select2(*this, "adpcm_select2"),
+		m_soundbank(*this, "soundbank")
+	{
 	}
 
-	uint8_t m_automat_adpcm_byte;
-	int m_automat_msm5205_vclk_toggle;
+	required_device<msm5205_device> m_msm1;
+	required_device<msm5205_device> m_msm2;
+	required_device<ls157_device> m_adpcm_select1;
+	required_device<ls157_device> m_adpcm_select2;
+	required_memory_bank m_soundbank;
+
+	bool m_adpcm_toggle1;
+	bool m_adpcm_toggle2;
 	uint16_t m_automat_scroll_regs[4];
 
 	DECLARE_WRITE16_MEMBER(automat_control_w);
-	DECLARE_WRITE8_MEMBER(automat_adpcm_w);
+	DECLARE_WRITE16_MEMBER(secretab_sound_w);
 	DECLARE_READ16_MEMBER( automat_palette_r );
 	DECLARE_WRITE16_MEMBER( automat_palette_w );
 	DECLARE_WRITE16_MEMBER( automat_scroll_w )
 	{
 		COMBINE_DATA(&m_automat_scroll_regs[offset]);
 	}
-	DECLARE_WRITE_LINE_MEMBER(automat_vclk_cb);
+	DECLARE_READ8_MEMBER(sound_command_r);
+	DECLARE_WRITE8_MEMBER(sound_bankswitch_w);
+	DECLARE_WRITE_LINE_MEMBER(msm1_vclk_cb);
+	DECLARE_WRITE_LINE_MEMBER(msm2_vclk_cb);
 
 	virtual void machine_start() override;
 
diff --git a/src/mame/includes/eolith.h b/src/mame/includes/eolith.h
index 90c4455..5d2e859 100644
--- a/src/mame/includes/eolith.h
+++ b/src/mame/includes/eolith.h
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina,Pierpaolo Prazzoli
 
 #include "cpu/mcs51/mcs51.h"
diff --git a/src/mame/includes/epos.h b/src/mame/includes/epos.h
index 64b1878..2f8858d 100644
--- a/src/mame/includes/epos.h
+++ b/src/mame/includes/epos.h
@@ -12,18 +12,22 @@ public:
 	epos_state(const machine_config &mconfig, device_type type, const char *tag)
 		: driver_device(mconfig, type, tag),
 		m_videoram(*this, "videoram"),
+		m_inputs(*this, { "INPUTS", "INPUTS2" }),
 		m_maincpu(*this, "maincpu") { }
 
 	/* memory pointers */
 	required_shared_ptr<uint8_t> m_videoram;
+	optional_ioport_array<2> m_inputs;
 
 	/* video-related */
 	uint8_t    m_palette;
 
 	/* misc */
 	int      m_counter;
+	int      m_input_multiplex;
 	DECLARE_WRITE8_MEMBER(dealer_decrypt_rom);
 	DECLARE_WRITE8_MEMBER(port_1_w);
+	DECLARE_READ8_MEMBER(read_prta);
 	DECLARE_WRITE8_MEMBER(write_prtc);
 	DECLARE_WRITE8_MEMBER(flip_screen_w);
 	DECLARE_DRIVER_INIT(dealer);
diff --git a/src/mame/includes/equites.h b/src/mame/includes/equites.h
index e30699f..5de0b38 100644
--- a/src/mame/includes/equites.h
+++ b/src/mame/includes/equites.h
@@ -60,7 +60,6 @@ public:
 	uint8_t     m_ay_port_a;
 	uint8_t     m_ay_port_b;
 	uint8_t     m_eq_cymbal_ctrl;
-	emu_timer *m_nmi_timer;
 	emu_timer *m_adjuster_timer;
 	float     m_cymvol;
 	float     m_hihatvol;
@@ -84,8 +83,9 @@ public:
 	DECLARE_WRITE8_MEMBER(equites_c0f8_w);
 	DECLARE_WRITE8_MEMBER(equites_cymbal_ctrl_w);
 	DECLARE_WRITE8_MEMBER(equites_dac_latch_w);
+	DECLARE_WRITE8_MEMBER(equites_8155_porta_w);
 	DECLARE_WRITE8_MEMBER(equites_8155_portb_w);
-	DECLARE_WRITE8_MEMBER(equites_8155_w);
+	DECLARE_WRITE8_MEMBER(equites_8155_portc_w);
 	DECLARE_WRITE16_MEMBER(gekisou_unknown_bit_w);
 	DECLARE_READ16_MEMBER(equites_spriteram_kludge_r);
 	DECLARE_READ8_MEMBER(mcu_ram_r);
@@ -117,7 +117,7 @@ public:
 	DECLARE_PALETTE_INIT(splndrbt);
 	uint32_t screen_update_equites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
 	uint32_t screen_update_splndrbt(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
-	TIMER_CALLBACK_MEMBER(equites_nmi_callback);
+	DECLARE_WRITE_LINE_MEMBER(equites_8155_timer_pulse);
 	TIMER_CALLBACK_MEMBER(equites_frq_adjuster_callback);
 	TIMER_DEVICE_CALLBACK_MEMBER(equites_scanline);
 	TIMER_DEVICE_CALLBACK_MEMBER(splndrbt_scanline);
diff --git a/src/mame/includes/fcombat.h b/src/mame/includes/fcombat.h
index 60fd8dd..b5561e7 100644
--- a/src/mame/includes/fcombat.h
+++ b/src/mame/includes/fcombat.h
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 
 
diff --git a/src/mame/includes/freekick.h b/src/mame/includes/freekick.h
index c71635c..f9dcec5 100644
--- a/src/mame/includes/freekick.h
+++ b/src/mame/includes/freekick.h
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina,David Haywood
 
 
diff --git a/src/mame/includes/fromance.h b/src/mame/includes/fromance.h
index 0960aff..4f1256b 100644
--- a/src/mame/includes/fromance.h
+++ b/src/mame/includes/fromance.h
@@ -98,7 +98,8 @@ public:
 	TIMER_CALLBACK_MEMBER(crtc_interrupt_gen);
 	inline void get_fromance_tile_info( tile_data &tileinfo, int tile_index, int layer );
 	inline void get_nekkyoku_tile_info( tile_data &tileinfo, int tile_index, int layer );
-	void init_common(  );
+	void init_common();
+	void crtc_refresh();
 	DECLARE_WRITE_LINE_MEMBER(fromance_adpcm_int);
 	required_device<cpu_device> m_maincpu;
 	optional_device<msm5205_device> m_msm;
diff --git a/src/mame/includes/hanaawas.h b/src/mame/includes/hanaawas.h
index 2aa5558..e57ea6c 100644
--- a/src/mame/includes/hanaawas.h
+++ b/src/mame/includes/hanaawas.h
@@ -25,10 +25,13 @@ public:
 
 	/* misc */
 	int        m_mux;
+	uint8_t    m_coin_settings;
+	uint8_t    m_coin_impulse;
 	DECLARE_READ8_MEMBER(hanaawas_input_port_0_r);
 	DECLARE_WRITE8_MEMBER(hanaawas_inputs_mux_w);
 	DECLARE_WRITE8_MEMBER(hanaawas_videoram_w);
 	DECLARE_WRITE8_MEMBER(hanaawas_colorram_w);
+	DECLARE_WRITE8_MEMBER(key_matrix_status_w);
 	DECLARE_WRITE8_MEMBER(irq_ack_w);
 	TILE_GET_INFO_MEMBER(get_bg_tile_info);
 	virtual void machine_start() override;
diff --git a/src/mame/includes/homerun.h b/src/mame/includes/homerun.h
index 49d16b5..17c5f19 100644
--- a/src/mame/includes/homerun.h
+++ b/src/mame/includes/homerun.h
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /*************************************************************************
 
diff --git a/src/mame/includes/kaneko16.h b/src/mame/includes/kaneko16.h
index d021428..5cc0efa 100644
--- a/src/mame/includes/kaneko16.h
+++ b/src/mame/includes/kaneko16.h
@@ -164,10 +164,15 @@ public:
 	DECLARE_WRITE16_MEMBER(berlwall_spriteregs_w);
 
 	DECLARE_DRIVER_INIT(berlwall);
+	DECLARE_DRIVER_INIT(berlwallk);
+	DECLARE_DRIVER_INIT(berlwallt);
+	DECLARE_DRIVER_INIT(berlwall_common);
 	DECLARE_PALETTE_INIT(berlwall);
 	DECLARE_VIDEO_START(berlwall);
 	uint32_t screen_update_berlwall(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
 	void kaneko16_render_15bpp_bitmap(bitmap_rgb32 &bitmap, const rectangle &cliprect);
+
+	void patch_protection(uint32_t bra_offset,uint16_t bra_value,uint16_t checksum);
 };
 
 class kaneko16_shogwarr_state : public kaneko16_state
diff --git a/src/mame/includes/ksayakyu.h b/src/mame/includes/ksayakyu.h
index 37cf048..53cc749 100644
--- a/src/mame/includes/ksayakyu.h
+++ b/src/mame/includes/ksayakyu.h
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 
 /*************************************************************************
diff --git a/src/mame/includes/ladyfrog.h b/src/mame/includes/ladyfrog.h
index 736f63d..5e4138d 100644
--- a/src/mame/includes/ladyfrog.h
+++ b/src/mame/includes/ladyfrog.h
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /*************************************************************************
 
diff --git a/src/mame/includes/leland.h b/src/mame/includes/leland.h
index c4e4670..d7dc210 100644
--- a/src/mame/includes/leland.h
+++ b/src/mame/includes/leland.h
@@ -65,7 +65,6 @@ public:
 	uint8_t *m_xrom_base;
 	uint32_t m_master_length;
 	uint32_t m_slave_length;
-	uint32_t m_xrom_length;
 	int m_dangerz_x;
 	int m_dangerz_y;
 	uint8_t m_analog_result;
@@ -93,6 +92,7 @@ public:
 	uint8_t m_gfxbank;
 	uint16_t m_last_scanline;
 	emu_timer *m_scanline_timer;
+
 	DECLARE_READ8_MEMBER(cerberus_dial_1_r);
 	DECLARE_READ8_MEMBER(cerberus_dial_2_r);
 	DECLARE_WRITE8_MEMBER(alleymas_joystick_kludge);
@@ -138,6 +138,12 @@ public:
 	DECLARE_WRITE8_MEMBER(ataxx_svram_port_w);
 	DECLARE_READ8_MEMBER(ataxx_mvram_port_r);
 	DECLARE_READ8_MEMBER(ataxx_svram_port_r);
+	DECLARE_READ8_MEMBER(ataxx_eeprom_r);
+	DECLARE_WRITE8_MEMBER(ataxx_eeprom_w);
+	DECLARE_READ8_MEMBER(leland_sound_port_r);
+	DECLARE_WRITE8_MEMBER(leland_sound_port_w);
+	DECLARE_WRITE8_MEMBER(leland_gfx_port_w);
+
 	DECLARE_DRIVER_INIT(dblplay);
 	DECLARE_DRIVER_INIT(viper);
 	DECLARE_DRIVER_INIT(quarterb);
@@ -171,6 +177,7 @@ public:
 	DECLARE_VIDEO_START(leland);
 	DECLARE_VIDEO_START(leland2);
 	DECLARE_VIDEO_START(ataxx);
+
 	uint32_t screen_update_leland(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
 	uint32_t screen_update_ataxx(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
 	INTERRUPT_GEN_MEMBER(leland_master_interrupt);
@@ -178,15 +185,12 @@ public:
 	TIMER_CALLBACK_MEMBER(ataxx_interrupt_callback);
 	TIMER_CALLBACK_MEMBER(scanline_callback);
 	TIMER_CALLBACK_MEMBER(leland_delayed_mvram_w);
-	DECLARE_READ8_MEMBER(ataxx_eeprom_r);
-	DECLARE_WRITE8_MEMBER(ataxx_eeprom_w);
-	DECLARE_READ8_MEMBER(leland_sound_port_r);
-	DECLARE_WRITE8_MEMBER(leland_sound_port_w);
-	DECLARE_WRITE8_MEMBER(leland_gfx_port_w);
+
 	void leland_video_addr_w(address_space &space, int offset, int data, int num);
 	int leland_vram_port_r(address_space &space, int offset, int num);
 	void leland_vram_port_w(address_space &space, int offset, int data, int num);
 	int dial_compute_value(int new_val, int indx);
+
 	void update_dangerz_xy();
 	void cerberus_bankswitch();
 	void mayhem_bankswitch();
diff --git a/src/mame/includes/mcr.h b/src/mame/includes/mcr.h
index 7ceb376..37498e9 100644
--- a/src/mame/includes/mcr.h
+++ b/src/mame/includes/mcr.h
@@ -13,6 +13,7 @@
 #include "machine/z80dart.h"
 #include "machine/watchdog.h"
 #include "audio/midway.h"
+#include "audio/csd.h"
 #include "sound/samples.h"
 
 /* constants */
@@ -32,7 +33,7 @@ public:
 		m_paletteram(*this, "paletteram"),
 		m_sio(*this, "ipu_sio"),
 		m_ssio(*this, "ssio"),
-		m_chip_squeak_deluxe(*this, "csd"),
+		m_cheap_squeak_deluxe(*this, "csd"),
 		m_sounds_good(*this, "sg"),
 		m_turbo_chip_squeak(*this, "tcs"),
 		m_squawk_n_talk(*this, "snt"),
@@ -52,7 +53,7 @@ public:
 
 	optional_device<z80dart_device> m_sio;
 	optional_device<midway_ssio_device> m_ssio;
-	optional_device<midway_chip_squeak_deluxe_device> m_chip_squeak_deluxe;
+	optional_device<midway_cheap_squeak_deluxe_device> m_cheap_squeak_deluxe;
 	optional_device<midway_sounds_good_device> m_sounds_good;
 	optional_device<midway_turbo_chip_squeak_device> m_turbo_chip_squeak;
 	optional_device<midway_squawk_n_talk_device> m_squawk_n_talk;
diff --git a/src/mame/includes/mcr68.h b/src/mame/includes/mcr68.h
index a290a81..e27097d 100644
--- a/src/mame/includes/mcr68.h
+++ b/src/mame/includes/mcr68.h
@@ -6,40 +6,27 @@
 
 ***************************************************************************/
 
-#include "machine/6821pia.h"
 #include "machine/watchdog.h"
 #include "audio/midway.h"
 #include "audio/williams.h"
-
-struct counter_state
-{
-	uint8_t           control;
-	uint16_t          latch;
-	uint16_t          count;
-	emu_timer *     timer;
-	uint8_t           timer_active;
-	attotime        period;
-};
+#include "machine/6840ptm.h"
 
 class mcr68_state : public driver_device
 {
 public:
 	mcr68_state(const machine_config &mconfig, device_type type, const char *tag)
 		: driver_device(mconfig, type, tag),
-		m_chip_squeak_deluxe(*this, "csd"),
 		m_sounds_good(*this, "sg"),
 		m_turbo_chip_squeak(*this, "tcs"),
 		m_cvsd_sound(*this, "cvsd"),
 		m_videoram(*this, "videoram"),
 		m_spriteram(*this, "spriteram") ,
 		m_maincpu(*this, "maincpu"),
-		m_watchdog(*this, "watchdog"),
 		m_gfxdecode(*this, "gfxdecode"),
 		m_screen(*this, "screen"),
-		m_palette(*this, "palette")
+		m_ptm(*this, "ptm")
 	{ }
 
-	optional_device<midway_chip_squeak_deluxe_device> m_chip_squeak_deluxe;
 	optional_device<midway_sounds_good_device> m_sounds_good;
 	optional_device<midway_turbo_chip_squeak_device> m_turbo_chip_squeak;
 	optional_device<williams_cvsd_sound_device> m_cvsd_sound;
@@ -51,22 +38,9 @@ public:
 	attotime m_timing_factor;
 	uint8_t m_sprite_clip;
 	int8_t m_sprite_xoffset;
-	uint8_t m_m6840_status;
-	uint8_t m_m6840_status_read_since_int;
-	uint8_t m_m6840_msb_buffer;
-	uint8_t m_m6840_lsb_buffer;
-	uint8_t m_m6840_irq_state;
-	uint8_t m_m6840_irq_vector;
-	struct counter_state m_m6840_state[3];
-	uint8_t m_v493_irq_state;
-	uint8_t m_v493_irq_vector;
 	timer_expired_delegate m_v493_callback;
-	uint8_t m_zwackery_sound_data;
-	attotime m_m6840_counter_periods[3];
-	attotime m_m6840_internal_counter_period;
 	tilemap_t *m_bg_tilemap;
 	tilemap_t *m_fg_tilemap;
-	DECLARE_READ16_MEMBER(zwackery_6840_r);
 	DECLARE_WRITE16_MEMBER(xenophobe_control_w);
 	DECLARE_WRITE16_MEMBER(blasted_control_w);
 	DECLARE_READ16_MEMBER(spyhunt2_port_0_r);
@@ -79,21 +53,9 @@ public:
 	DECLARE_READ16_MEMBER(pigskin_port_1_r);
 	DECLARE_READ16_MEMBER(pigskin_port_2_r);
 	DECLARE_READ16_MEMBER(trisport_port_1_r);
-	DECLARE_WRITE16_MEMBER(mcr68_6840_upper_w);
-	DECLARE_WRITE16_MEMBER(mcr68_6840_lower_w);
-	DECLARE_READ16_MEMBER(mcr68_6840_upper_r);
-	DECLARE_READ16_MEMBER(mcr68_6840_lower_r);
-	DECLARE_WRITE8_MEMBER(mcr68_6840_w_common);
-	DECLARE_READ16_MEMBER(mcr68_6840_r_common);
-	void reload_count(int counter);
-	uint16_t compute_counter(int counter);
 	DECLARE_WRITE16_MEMBER(mcr68_videoram_w);
-	DECLARE_WRITE16_MEMBER(zwackery_videoram_w);
-	DECLARE_WRITE16_MEMBER(zwackery_spriteram_w);
-	DECLARE_READ8_MEMBER(zwackery_port_2_r);
 	DECLARE_DRIVER_INIT(intlaser);
 	DECLARE_DRIVER_INIT(pigskin);
-	DECLARE_DRIVER_INIT(zwackery);
 	DECLARE_DRIVER_INIT(blasted);
 	DECLARE_DRIVER_INIT(trisport);
 	DECLARE_DRIVER_INIT(xenophob);
@@ -102,40 +64,21 @@ public:
 	DECLARE_DRIVER_INIT(archrivlb);
 	DECLARE_READ16_MEMBER(archrivlb_port_1_r);
 	TILE_GET_INFO_MEMBER(get_bg_tile_info);
-	TILE_GET_INFO_MEMBER(zwackery_get_bg_tile_info);
-	TILE_GET_INFO_MEMBER(zwackery_get_fg_tile_info);
-	DECLARE_MACHINE_START(zwackery);
-	DECLARE_MACHINE_RESET(zwackery);
-	DECLARE_VIDEO_START(zwackery);
 	DECLARE_MACHINE_START(mcr68);
 	DECLARE_MACHINE_RESET(mcr68);
 	DECLARE_VIDEO_START(mcr68);
-	uint32_t screen_update_zwackery(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
 	uint32_t screen_update_mcr68(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
-	INTERRUPT_GEN_MEMBER(mcr68_interrupt);
+	TIMER_DEVICE_CALLBACK_MEMBER(scanline_cb);
 	TIMER_CALLBACK_MEMBER(mcr68_493_off_callback);
 	TIMER_CALLBACK_MEMBER(mcr68_493_callback);
-	TIMER_CALLBACK_MEMBER(zwackery_493_off_callback);
-	TIMER_CALLBACK_MEMBER(zwackery_493_callback);
-	TIMER_CALLBACK_MEMBER(counter_fired_callback);
-	DECLARE_READ8_MEMBER(zwackery_port_1_r);
-	DECLARE_READ8_MEMBER(zwackery_port_3_r);
-	DECLARE_WRITE8_MEMBER(zwackery_pia0_w);
-	DECLARE_WRITE8_MEMBER(zwackery_pia1_w);
-	DECLARE_WRITE_LINE_MEMBER(zwackery_ca2_w);
-	DECLARE_WRITE_LINE_MEMBER(zwackery_pia_irq);
 	void mcr68_update_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int priority);
-	void zwackery_update_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int priority);
-	void mcr68_common_init();
-	void update_mcr68_interrupts();
-	inline void update_interrupts();
-	void subtract_from_counter(int counter, int count);
 	void mcr68_common_init(int clip, int xoffset);
 	required_device<cpu_device> m_maincpu;
-	required_device<watchdog_timer_device> m_watchdog;
 	required_device<gfxdecode_device> m_gfxdecode;
 	required_device<screen_device> m_screen;
-	required_device<palette_device> m_palette;
 	std::unique_ptr<uint8_t[]> m_srcdata0;
 	std::unique_ptr<uint8_t[]> m_srcdata2;
+
+private:
+	required_device<ptm6840_device> m_ptm;
 };
diff --git a/src/mame/includes/midwunit.h b/src/mame/includes/midwunit.h
index 805f0fc..618ef62 100644
--- a/src/mame/includes/midwunit.h
+++ b/src/mame/includes/midwunit.h
@@ -13,13 +13,15 @@ class midwunit_state : public midtunit_state
 public:
 	midwunit_state(const machine_config &mconfig, device_type type, const char *tag)
 		: midtunit_state(mconfig, type, tag),
-			m_midway_serial_pic(*this, "serial_pic"),
+			m_midway_serial_pic(*this, "serial_security_sim"),
+			m_midway_serial_pic_emu(*this, "serial_security"),
 			m_nvram(*this, "nvram"),
 			m_mainram(*this, "mainram"),
 			m_ports(*this, { { "IN0", "IN1", "DSW", "IN2" } })
 			{ }
 
-	required_device<midway_serial_pic_device> m_midway_serial_pic;
+	optional_device<midway_serial_pic_device> m_midway_serial_pic;
+	optional_device<midway_serial_pic_emu_device> m_midway_serial_pic_emu;
 	required_shared_ptr<uint16_t> m_nvram;
 	required_shared_ptr<uint16_t> m_mainram;
 	required_ioport_array<4> m_ports;
diff --git a/src/mame/includes/mitchell.h b/src/mame/includes/mitchell.h
index 441b43e..01ccf76 100644
--- a/src/mame/includes/mitchell.h
+++ b/src/mame/includes/mitchell.h
@@ -6,11 +6,12 @@
 
 *************************************************************************/
 
-#include "sound/okim6295.h"
+#include "machine/74157.h"
 #include "machine/nvram.h"
 #include "machine/eepromser.h"
 #include "machine/gen_latch.h"
 #include "sound/msm5205.h"
+#include "sound/okim6295.h"
 
 class mitchell_state : public driver_device
 {
@@ -19,10 +20,11 @@ public:
 		: driver_device(mconfig, type, tag),
 		m_maincpu(*this, "maincpu"),
 		m_audiocpu(*this, "audiocpu"),
-		m_oki(*this, "oki") ,
+		m_oki(*this, "oki"),
 		m_nvram(*this, "nvram"),
 		m_eeprom(*this, "eeprom"),
 		m_msm(*this, "msm"),
+		m_adpcm_select(*this, "adpcm_select"),
 		m_gfxdecode(*this, "gfxdecode"),
 		m_palette(*this, "palette"),
 		m_soundlatch(*this, "soundlatch"),
@@ -30,7 +32,8 @@ public:
 		m_videoram(*this, "videoram"),
 		m_bank1(*this, "bank1"),
 		m_bank0d(*this, "bank0d"),
-		m_bank1d(*this, "bank1d") { }
+		m_bank1d(*this, "bank1d"),
+		m_soundbank(*this, "soundbank") { }
 
 	/* devices */
 	required_device<cpu_device> m_maincpu;
@@ -39,6 +42,7 @@ public:
 	optional_device<nvram_device> m_nvram;
 	optional_device<eeprom_serial_93cxx_device> m_eeprom;
 	optional_device<msm5205_device> m_msm;
+	optional_device<ls157_device> m_adpcm_select;
 	required_device<gfxdecode_device> m_gfxdecode;
 	required_device<palette_device> m_palette;
 	optional_device<generic_latch_8_device> m_soundlatch;
@@ -49,6 +53,7 @@ public:
 	required_memory_bank m_bank1;
 	optional_memory_bank m_bank0d;
 	optional_memory_bank m_bank1d;
+	optional_memory_bank m_soundbank;
 
 	/* video-related */
 	tilemap_t    *m_bg_tilemap;
@@ -59,8 +64,7 @@ public:
 	std::vector<uint8_t> m_paletteram;
 
 	/* sound-related */
-	int        m_sample_buffer;
-	int        m_sample_select;
+	bool       m_sample_select;
 
 	/* misc */
 	int        m_input_type;
@@ -127,5 +131,8 @@ public:
 	void draw_sprites( bitmap_ind16 &bitmap, const rectangle &cliprect );
 	void bootleg_decode();
 	void configure_banks(void (*decode)(uint8_t *src, uint8_t *dst, int size));
+	DECLARE_WRITE8_MEMBER(sound_command_w);
+	DECLARE_READ8_MEMBER(sound_command_r);
+	DECLARE_WRITE8_MEMBER(sound_bankswitch_w);
 	DECLARE_WRITE_LINE_MEMBER(spangbl_adpcm_int);
 };
diff --git a/src/mame/includes/model1.h b/src/mame/includes/model1.h
index 04c8f9c..ce82135 100644
--- a/src/mame/includes/model1.h
+++ b/src/mame/includes/model1.h
@@ -86,6 +86,11 @@ public:
 	DECLARE_READ32_MEMBER(copro_fifoin_pop);
 	DECLARE_WRITE32_MEMBER(copro_fifoout_push);
 
+	uint16_t m_r360_state;
+	DECLARE_DRIVER_INIT(wingwar360);
+	DECLARE_READ16_MEMBER(r360_r);
+	DECLARE_WRITE16_MEMBER(r360_w);
+
 	// Rendering
 	DECLARE_VIDEO_START(model1);
 	DECLARE_READ16_MEMBER(model1_listctl_r);
diff --git a/src/mame/includes/model2.h b/src/mame/includes/model2.h
index 09348dd..8fc3829 100644
--- a/src/mame/includes/model2.h
+++ b/src/mame/includes/model2.h
@@ -5,6 +5,7 @@
 #include "audio/segam1audio.h"
 #include "machine/eepromser.h"
 #include "cpu/i960/i960.h"
+#include "cpu/mb86235/mb86235.h"
 #include "sound/scsp.h"
 #include "machine/315-5881_crypt.h"
 #include "machine/315-5838_317-0229_comp.h"
@@ -67,7 +68,7 @@ public:
 	optional_device<cpu_device> m_audiocpu;
 	optional_device<cpu_device> m_tgp;
 	optional_device<cpu_device> m_dsp;
-	optional_device<cpu_device> m_tgpx4;
+	optional_device<mb86235_device> m_tgpx4;
 	optional_device<cpu_device> m_drivecpu;
 	required_device<eeprom_serial_93cxx_device> m_eeprom;
 	required_device<screen_device> m_screen;
diff --git a/src/mame/includes/mustache.h b/src/mame/includes/mustache.h
index 7d7be43..f0f13bd 100644
--- a/src/mame/includes/mustache.h
+++ b/src/mame/includes/mustache.h
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 #include "audio/seibu.h"    // for seibu_sound_decrypt on the MAIN cpu (not sound)
 
@@ -12,7 +12,8 @@ public:
 		m_screen(*this, "screen"),
 		m_palette(*this, "palette"),
 		m_videoram(*this, "videoram"),
-		m_spriteram(*this, "spriteram") { }
+		m_spriteram(*this, "spriteram"),
+		m_dswb(*this, "DSWB") { }
 
 	required_device<cpu_device> m_maincpu;
 	required_device<gfxdecode_device> m_gfxdecode;
@@ -22,6 +23,8 @@ public:
 	required_shared_ptr<uint8_t> m_videoram;
 	required_shared_ptr<uint8_t> m_spriteram;
 
+	required_ioport m_dswb;
+
 	tilemap_t *m_bg_tilemap;
 	int m_control_byte;
 
diff --git a/src/mame/includes/nycaptor.h b/src/mame/includes/nycaptor.h
index 87f30a9..267d627 100644
--- a/src/mame/includes/nycaptor.h
+++ b/src/mame/includes/nycaptor.h
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 
 #include "machine/gen_latch.h"
diff --git a/src/mame/includes/pacman.h b/src/mame/includes/pacman.h
index e9e15c4..cbfe2da 100644
--- a/src/mame/includes/pacman.h
+++ b/src/mame/includes/pacman.h
@@ -155,14 +155,14 @@ public:
 	void eyes_decode(uint8_t *data);
 	void mspacman_install_patches(uint8_t *ROM);
 
-	// theglopb.c
-	void theglobp_decrypt_rom_8();
-	void theglobp_decrypt_rom_9();
-	void theglobp_decrypt_rom_A();
-	void theglobp_decrypt_rom_B();
-	DECLARE_READ8_MEMBER(theglobp_decrypt_rom);
+	// epos.c
+	DECLARE_READ8_MEMBER(epos_decryption_w);
 	DECLARE_MACHINE_START(theglobp);
 	DECLARE_MACHINE_RESET(theglobp);
+	DECLARE_MACHINE_START(eeekk);
+	DECLARE_MACHINE_RESET(eeekk);
+	DECLARE_MACHINE_START(acitya);
+	DECLARE_MACHINE_RESET(acitya);
 
 	// pacplus.c
 	uint8_t pacplus_decrypt(int addr, uint8_t e);
@@ -171,13 +171,4 @@ public:
 	// jumpshot.c
 	uint8_t jumpshot_decrypt(int addr, uint8_t e);
 	void jumpshot_decode();
-
-	// acitya.c
-	void acitya_decrypt_rom_8();
-	void acitya_decrypt_rom_9();
-	void acitya_decrypt_rom_A();
-	void acitya_decrypt_rom_B();
-	DECLARE_READ8_MEMBER(acitya_decrypt_rom);
-	DECLARE_MACHINE_START(acitya);
-	DECLARE_MACHINE_RESET(acitya);
 };
diff --git a/src/mame/includes/pitnrun.h b/src/mame/includes/pitnrun.h
index 0e352c9..8136a9a 100644
--- a/src/mame/includes/pitnrun.h
+++ b/src/mame/includes/pitnrun.h
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina, Pierpaolo Prazzoli
 class pitnrun_state : public driver_device
 {
diff --git a/src/mame/includes/pk8000.h b/src/mame/includes/pk8000.h
index 39d49bd..b4dc661 100644
--- a/src/mame/includes/pk8000.h
+++ b/src/mame/includes/pk8000.h
@@ -7,34 +7,35 @@ public:
 		: driver_device(mconfig, type, tag) ,
 		m_maincpu(*this, "maincpu") { }
 
-	DECLARE_READ8_MEMBER(pk8000_video_color_r);
-	DECLARE_WRITE8_MEMBER(pk8000_video_color_w);
-	DECLARE_READ8_MEMBER(pk8000_text_start_r);
-	DECLARE_WRITE8_MEMBER(pk8000_text_start_w);
-	DECLARE_READ8_MEMBER(pk8000_chargen_start_r);
-	DECLARE_WRITE8_MEMBER(pk8000_chargen_start_w);
-	DECLARE_READ8_MEMBER(pk8000_video_start_r);
-	DECLARE_WRITE8_MEMBER(pk8000_video_start_w);
-	DECLARE_READ8_MEMBER(pk8000_color_start_r);
-	DECLARE_WRITE8_MEMBER(pk8000_color_start_w);
-	DECLARE_READ8_MEMBER(pk8000_color_r);
-	DECLARE_WRITE8_MEMBER(pk8000_color_w);
-	DECLARE_READ8_MEMBER(pk8000_84_porta_r);
-	DECLARE_WRITE8_MEMBER(pk8000_84_porta_w);
-	DECLARE_WRITE8_MEMBER(pk8000_84_portc_w);
+	DECLARE_READ8_MEMBER(video_color_r);
+	DECLARE_WRITE8_MEMBER(video_color_w);
+	DECLARE_READ8_MEMBER(text_start_r);
+	DECLARE_WRITE8_MEMBER(text_start_w);
+	DECLARE_READ8_MEMBER(chargen_start_r);
+	DECLARE_WRITE8_MEMBER(chargen_start_w);
+	DECLARE_READ8_MEMBER(video_start_r);
+	DECLARE_WRITE8_MEMBER(video_start_w);
+	DECLARE_READ8_MEMBER(color_start_r);
+	DECLARE_WRITE8_MEMBER(color_start_w);
+	DECLARE_READ8_MEMBER(color_r);
+	DECLARE_WRITE8_MEMBER(color_w);
+	DECLARE_READ8_MEMBER(_84_porta_r);
+	DECLARE_WRITE8_MEMBER(_84_porta_w);
+	DECLARE_WRITE8_MEMBER(_84_portc_w);
 
 	DECLARE_PALETTE_INIT(pk8000);
 
-	uint32_t pk8000_video_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, uint8_t *videomem);
+	uint32_t video_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, uint8_t *videomem);
+
 protected:
-	uint8_t m_pk8000_text_start;
-	uint8_t m_pk8000_chargen_start;
-	uint8_t m_pk8000_video_start;
-	uint8_t m_pk8000_color_start;
+	uint8_t m_text_start;
+	uint8_t m_chargen_start;
+	uint8_t m_video_start;
+	uint8_t m_color_start;
 
-	uint8_t m_pk8000_video_mode;
-	uint8_t m_pk8000_video_color;
-	uint8_t m_pk8000_color[32];
-	uint8_t m_pk8000_video_enable;
+	uint8_t m_video_mode;
+	uint8_t m_video_color;
+	uint8_t m_color[32];
+	uint8_t m_video_enable;
 	required_device<cpu_device> m_maincpu;
 };
diff --git a/src/mame/includes/playmark.h b/src/mame/includes/playmark.h
index 8ac6c84..1a86acd 100644
--- a/src/mame/includes/playmark.h
+++ b/src/mame/includes/playmark.h
@@ -16,6 +16,7 @@ public:
 		m_spriteram(*this, "spriteram"),
 		m_rowscroll(*this, "rowscroll"),
 		m_oki(*this, "oki"),
+		m_okibank(*this, "okibank"),
 		m_eeprom(*this, "eeprom"),
 		m_maincpu(*this, "maincpu"),
 		m_audiocpu(*this, "audiocpu"),
@@ -51,11 +52,13 @@ public:
 	uint16_t      m_snd_flag;
 	uint8_t       m_oki_control;
 	uint8_t       m_oki_command;
-	int         m_old_oki_bank;
 	uint8_t       m_dispenser_latch;
+	int         m_oki_numbanks;
+	void configure_oki_banks();
 
 	/* devices */
 	required_device<okim6295_device> m_oki;
+	optional_memory_bank m_okibank;
 	optional_device<eeprom_serial_93cxx_device> m_eeprom;
 	DECLARE_WRITE16_MEMBER(coinctrl_w);
 	DECLARE_WRITE16_MEMBER(wbeachvl_coin_eeprom_w);
diff --git a/src/mame/includes/rastan.h b/src/mame/includes/rastan.h
index 393a213..f66399d 100644
--- a/src/mame/includes/rastan.h
+++ b/src/mame/includes/rastan.h
@@ -5,6 +5,8 @@
     Rastan
 
 *************************************************************************/
+
+#include "machine/74157.h"
 #include "sound/msm5205.h"
 #include "video/pc080sn.h"
 #include "video/pc090oj.h"
@@ -17,21 +19,25 @@ public:
 		m_maincpu(*this, "maincpu"),
 		m_audiocpu(*this, "audiocpu"),
 		m_msm(*this, "msm"),
+		m_adpcm_sel(*this, "adpcm_sel"),
+		m_adpcm_data(*this, "adpcm"),
 		m_pc080sn(*this, "pc080sn"),
 		m_pc090oj(*this, "pc090oj") { }
 
 	/* video-related */
-	uint16_t      m_sprite_ctrl;
-	uint16_t      m_sprites_flipscreen;
+	u16         m_sprite_ctrl;
+	u16         m_sprites_flipscreen;
 
 	/* misc */
-	int         m_adpcm_pos;
-	int         m_adpcm_data;
+	u16         m_adpcm_pos;
+	bool        m_adpcm_ff;
 
 	/* devices */
 	required_device<cpu_device> m_maincpu;
 	required_device<cpu_device> m_audiocpu;
 	required_device<msm5205_device> m_msm;
+	required_device<ls157_device> m_adpcm_sel;
+	required_region_ptr<u8> m_adpcm_data;
 	required_device<pc080sn_device> m_pc080sn;
 	required_device<pc090oj_device> m_pc090oj;
 	DECLARE_WRITE8_MEMBER(rastan_msm5205_address_w);
diff --git a/src/mame/includes/rltennis.h b/src/mame/includes/rltennis.h
index 986244b..c2d3b88 100644
--- a/src/mame/includes/rltennis.h
+++ b/src/mame/includes/rltennis.h
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 #include "sound/dac.h"
 
diff --git a/src/mame/includes/segas16b.h b/src/mame/includes/segas16b.h
index b47037f..c69cd5c 100644
--- a/src/mame/includes/segas16b.h
+++ b/src/mame/includes/segas16b.h
@@ -89,6 +89,7 @@ public:
 	// other callbacks
 	DECLARE_WRITE_LINE_MEMBER(upd7759_generate_nmi);
 	INTERRUPT_GEN_MEMBER( i8751_main_cpu_vblank );
+	DECLARE_WRITE8_MEMBER(spin_68k_w);
 
 	// ROM board-specific driver init
 	DECLARE_DRIVER_INIT(generic_5521);
@@ -113,7 +114,6 @@ public:
 	DECLARE_DRIVER_INIT(goldnaxe_5704);
 	DECLARE_DRIVER_INIT(defense_5358_small);
 	DECLARE_DRIVER_INIT(sjryuko_5358_small);
-	DECLARE_DRIVER_INIT(altbeast_5521);
 	DECLARE_DRIVER_INIT(exctleag_5358);
 	DECLARE_DRIVER_INIT(tetrbx);
 	DECLARE_DRIVER_INIT(aceattac_5358);
@@ -123,7 +123,6 @@ public:
 	DECLARE_DRIVER_INIT(dunkshot_5358_small);
 	DECLARE_DRIVER_INIT(timescan_5358_small);
 	DECLARE_DRIVER_INIT(shinobi3_5358);
-	DECLARE_DRIVER_INIT(goldnaxe_5797);
 	DECLARE_DRIVER_INIT(altbeas4_5521);
 	DECLARE_DRIVER_INIT(aliensyn7_5358_small);
 
@@ -171,7 +170,6 @@ protected:
 	void altbeast_common_i8751_sim(offs_t soundoffs, offs_t inputoffs, int alt_bank);
 	void altbeasj_i8751_sim();
 	void altbeas5_i8751_sim();
-	void altbeast_i8751_sim();
 	void ddux_i8751_sim();
 	void goldnaxe_i8751_sim();
 	void tturf_i8751_sim();
diff --git a/src/mame/includes/seta.h b/src/mame/includes/seta.h
index 2b70602..e3e9a88 100644
--- a/src/mame/includes/seta.h
+++ b/src/mame/includes/seta.h
@@ -55,7 +55,6 @@ public:
 		m_dsw2_3(*this, "DSW2_3"),
 		m_bet(*this, {"BET0", "BET1", "BET2", "BET3", "BET4"}),
 		m_sharedram(*this,"sharedram"),
-		m_workram(*this,"workram"),
 		m_vregs(*this,"vregs"),
 		m_vram_0(*this,"vram_0"),
 		m_vctrl_0(*this,"vctrl_0"),
@@ -92,7 +91,6 @@ public:
 	optional_ioport_array<5> m_bet;
 
 	optional_shared_ptr<uint8_t> m_sharedram;
-	optional_shared_ptr<uint16_t> m_workram;
 	optional_shared_ptr<uint16_t> m_vregs;
 	optional_shared_ptr<uint16_t> m_vram_0;
 	optional_shared_ptr<uint16_t> m_vctrl_0;
diff --git a/src/mame/includes/shootout.h b/src/mame/includes/shootout.h
index fc1486b..4a09657 100644
--- a/src/mame/includes/shootout.h
+++ b/src/mame/includes/shootout.h
@@ -29,9 +29,11 @@ public:
 
 	tilemap_t *m_background;
 	tilemap_t *m_foreground;
-	int m_bFlicker;
+
+	int m_ccnt_old_val;
 
 	DECLARE_WRITE8_MEMBER(bankswitch_w);
+	DECLARE_READ8_MEMBER(sound_cpu_command_r);
 	DECLARE_WRITE8_MEMBER(sound_cpu_command_w);
 	DECLARE_WRITE8_MEMBER(flipscreen_w);
 	DECLARE_WRITE8_MEMBER(coincounter_w);
@@ -41,7 +43,10 @@ public:
 	DECLARE_INPUT_CHANGED_MEMBER(coin_inserted);
 
 	DECLARE_DRIVER_INIT(shootout);
+
+	virtual void machine_reset() override;
 	virtual void video_start() override;
+
 	DECLARE_PALETTE_INIT(shootout);
 
 	TILE_GET_INFO_MEMBER(get_bg_tile_info);
diff --git a/src/mame/includes/sidepckt.h b/src/mame/includes/sidepckt.h
index ec6cb6d..9775130 100644
--- a/src/mame/includes/sidepckt.h
+++ b/src/mame/includes/sidepckt.h
@@ -40,13 +40,15 @@ public:
 	uint8_t m_current_table;
 	uint8_t m_in_math;
 	uint8_t m_math_param;
+	uint8_t m_scroll_y;
 
 	DECLARE_WRITE8_MEMBER(sound_cpu_command_w);
 	DECLARE_READ8_MEMBER(i8751_r);
 	DECLARE_WRITE8_MEMBER(i8751_w);
 	DECLARE_WRITE8_MEMBER(videoram_w);
 	DECLARE_WRITE8_MEMBER(colorram_w);
-	DECLARE_WRITE8_MEMBER(flipscreen_w);
+	DECLARE_READ8_MEMBER(scroll_y_r);
+	DECLARE_WRITE8_MEMBER(scroll_y_w);
 
 	DECLARE_DRIVER_INIT(sidepckt);
 	DECLARE_DRIVER_INIT(sidepcktj);
diff --git a/src/mame/includes/simple_st0016.h b/src/mame/includes/simple_st0016.h
index 9b535c8..5167537 100644
--- a/src/mame/includes/simple_st0016.h
+++ b/src/mame/includes/simple_st0016.h
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 
 #include "machine/st0016.h"
diff --git a/src/mame/includes/slapfght.h b/src/mame/includes/slapfght.h
index 7b2f019..9b3a66f 100644
--- a/src/mame/includes/slapfght.h
+++ b/src/mame/includes/slapfght.h
@@ -65,15 +65,10 @@ public:
 	bool m_main_sent;
 	uint8_t m_from_main;
 	uint8_t m_from_mcu;
-	uint8_t m_portA_in;
-	uint8_t m_portA_out;
-	uint8_t m_ddrA;
-	uint8_t m_portB_in;
-	uint8_t m_portB_out;
-	uint8_t m_ddrB;
-	uint8_t m_portC_in;
-	uint8_t m_portC_out;
-	uint8_t m_ddrC;
+
+	uint8_t m_from_mcu_latch;
+	uint8_t m_to_mcu_latch;
+	uint8_t m_old_portB;
 
 	int m_getstar_status;
 	int m_getstar_sequence_index;
@@ -102,25 +97,16 @@ public:
 	DECLARE_WRITE8_MEMBER(tigerh_mcu_w);
 	DECLARE_READ8_MEMBER(tigerh_mcu_r);
 	DECLARE_READ8_MEMBER(tigerh_mcu_status_r);
-	DECLARE_READ8_MEMBER(tigerh_68705_portA_r);
-	DECLARE_WRITE8_MEMBER(tigerh_68705_portA_w);
-	DECLARE_WRITE8_MEMBER(tigerh_68705_ddrA_w);
-	DECLARE_READ8_MEMBER(tigerh_68705_portB_r);
-	DECLARE_WRITE8_MEMBER(tigerh_68705_portB_w);
-	DECLARE_WRITE8_MEMBER(tigerh_68705_ddrB_w);
-	DECLARE_READ8_MEMBER(tigerh_68705_portC_r);
-	DECLARE_WRITE8_MEMBER(tigerh_68705_portC_w);
-	DECLARE_WRITE8_MEMBER(tigerh_68705_ddrC_w);
-
-	DECLARE_READ8_MEMBER(slapfight_68705_portA_r);
-	DECLARE_WRITE8_MEMBER(slapfight_68705_portA_w);
-	DECLARE_WRITE8_MEMBER(slapfight_68705_ddrA_w);
-	DECLARE_READ8_MEMBER(slapfight_68705_portB_r);
-	DECLARE_WRITE8_MEMBER(slapfight_68705_portB_w);
-	DECLARE_WRITE8_MEMBER(slapfight_68705_ddrB_w);
-	DECLARE_READ8_MEMBER(slapfight_68705_portC_r);
-	DECLARE_WRITE8_MEMBER(slapfight_68705_portC_w);
-	DECLARE_WRITE8_MEMBER(slapfight_68705_ddrC_w);
+
+	DECLARE_READ8_MEMBER(tigerh_mcu_porta_r);
+	DECLARE_WRITE8_MEMBER(tigerh_mcu_porta_w);
+
+	DECLARE_WRITE8_MEMBER(tigerh_mcu_portb_w);
+	DECLARE_WRITE8_MEMBER(slapfght_mcu_portb_w);
+
+	DECLARE_READ8_MEMBER(tigerh_mcu_portc_r);
+	DECLARE_READ8_MEMBER(slapfght_mcu_portc_r);
+
 
 	DECLARE_READ8_MEMBER(getstar_mcusim_r);
 	DECLARE_WRITE8_MEMBER(getstar_mcusim_w);
diff --git a/src/mame/includes/srmp2.h b/src/mame/includes/srmp2.h
index f05170a..54b4c81 100644
--- a/src/mame/includes/srmp2.h
+++ b/src/mame/includes/srmp2.h
@@ -53,13 +53,12 @@ public:
 	DECLARE_WRITE8_MEMBER(srmp2_irq2_ack_w);
 	DECLARE_WRITE8_MEMBER(srmp2_irq4_ack_w);
 	DECLARE_WRITE16_MEMBER(srmp2_flags_w);
-	DECLARE_WRITE16_MEMBER(srmp2_adpcm_code_w);
+	DECLARE_WRITE8_MEMBER(adpcm_code_w);
 
 	// srmp3
 	DECLARE_WRITE8_MEMBER(srmp3_rombank_w);
 	DECLARE_WRITE8_MEMBER(srmp3_flags_w);
 	DECLARE_WRITE8_MEMBER(srmp3_irq_ack_w);
-	DECLARE_WRITE8_MEMBER(srmp3_adpcm_code_w);
 
 	virtual void machine_start() override;
 	DECLARE_MACHINE_START(srmp2);
diff --git a/src/mame/includes/ssrj.h b/src/mame/includes/ssrj.h
index 52bc152..19d2cf1 100644
--- a/src/mame/includes/ssrj.h
+++ b/src/mame/includes/ssrj.h
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 class ssrj_state : public driver_device
 {
diff --git a/src/mame/includes/system16.h b/src/mame/includes/system16.h
index cd297a8..3cc3197 100644
--- a/src/mame/includes/system16.h
+++ b/src/mame/includes/system16.h
@@ -2,6 +2,7 @@
 // copyright-holders:Nicola Salmoria, Phil Stroffolino, Mirko Buffoni
 
 #include "video/sega16sp.h"
+#include "machine/74157.h"
 #include "machine/gen_latch.h"
 #include "machine/segaic16.h"
 #include "sound/msm5205.h"
@@ -18,6 +19,7 @@ public:
 		m_tileram(*this, "tileram"),
 		m_goldnaxeb2_bgpage(*this, "gab2_bgpage"),
 		m_goldnaxeb2_fgpage(*this, "gab2_fgpage"),
+		m_soundbank(*this, "soundbank"),
 		m_sprites(*this, "sprites"),
 		m_maincpu(*this, "maincpu"),
 		m_soundcpu(*this, "soundcpu"),
@@ -25,6 +27,7 @@ public:
 		m_upd7759(*this, "7759"),
 		m_gfxdecode(*this, "gfxdecode"),
 		m_soundlatch(*this, "soundlatch"),
+		m_adpcm_select(*this, "adpcm_select"),
 		m_decrypted_opcodes(*this, "decrypted_opcodes") { }
 
 	required_shared_ptr<uint16_t> m_textram;
@@ -34,6 +37,8 @@ public:
 	optional_shared_ptr<uint16_t> m_goldnaxeb2_bgpage;
 	optional_shared_ptr<uint16_t> m_goldnaxeb2_fgpage;
 
+	optional_memory_bank m_soundbank;
+
 	required_device<sega_16bit_sprite_device> m_sprites;
 
 	uint16_t m_coinctrl;
@@ -123,10 +128,13 @@ public:
 	optional_device<upd7759_device> m_upd7759;
 	required_device<gfxdecode_device> m_gfxdecode;
 	optional_device<generic_latch_8_device> m_soundlatch;
+	optional_device<ls157_device> m_adpcm_select;
 	optional_shared_ptr<uint16_t> m_decrypted_opcodes;
 
 	DECLARE_WRITE16_MEMBER(sound_command_nmi_w);
 	DECLARE_WRITE16_MEMBER(sound_command_irq_w);
+	DECLARE_READ8_MEMBER(sound_command_irq_r);
+	DECLARE_WRITE8_MEMBER(soundbank_msm_w);
 	DECLARE_WRITE16_MEMBER(sys16_coinctrl_w);
 	DECLARE_READ16_MEMBER(passht4b_service_r);
 	DECLARE_READ16_MEMBER(passht4b_io1_r);
@@ -218,6 +226,7 @@ public:
 	void set_bg_page( int data );
 	void datsu_set_pages(  );
 	DECLARE_WRITE_LINE_MEMBER(tturfbl_msm5205_callback);
+	DECLARE_WRITE_LINE_MEMBER(datsu_msm5205_callback);
 	DECLARE_WRITE_LINE_MEMBER(shdancbl_msm5205_callback);
 	DECLARE_WRITE_LINE_MEMBER(sound_cause_nmi);
 };
diff --git a/src/mame/includes/tail2nos.h b/src/mame/includes/tail2nos.h
index e9aa92d..3bf2cc0 100644
--- a/src/mame/includes/tail2nos.h
+++ b/src/mame/includes/tail2nos.h
@@ -34,6 +34,7 @@ public:
 	int         m_txbank;
 	int         m_txpalette;
 	int         m_video_enable;
+	uint8_t     m_pending_command;
 
 	/* devices */
 	required_device<cpu_device> m_maincpu;
@@ -43,11 +44,14 @@ public:
 	required_device<palette_device> m_palette;
 	required_device<generic_latch_8_device> m_soundlatch;
 
-	DECLARE_WRITE16_MEMBER(sound_command_w);
+	DECLARE_CUSTOM_INPUT_MEMBER(analog_in_r);
 	DECLARE_WRITE16_MEMBER(tail2nos_txvideoram_w);
 	DECLARE_WRITE16_MEMBER(tail2nos_zoomdata_w);
 	DECLARE_WRITE16_MEMBER(tail2nos_gfxbank_w);
+	DECLARE_WRITE8_MEMBER(sound_command_w);
 	DECLARE_WRITE8_MEMBER(sound_bankswitch_w);
+	DECLARE_WRITE8_MEMBER(sound_semaphore_w);
+	DECLARE_READ8_MEMBER(sound_semaphore_r);
 	TILE_GET_INFO_MEMBER(get_tile_info);
 	virtual void machine_start() override;
 	virtual void machine_reset() override;
diff --git a/src/mame/includes/taito_o.h b/src/mame/includes/taito_o.h
index a3ae26b..04ee97e 100644
--- a/src/mame/includes/taito_o.h
+++ b/src/mame/includes/taito_o.h
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /*************************************************************************
 
diff --git a/src/mame/includes/tnzs.h b/src/mame/includes/tnzs.h
index 6e57dc0..673ae0d 100644
--- a/src/mame/includes/tnzs.h
+++ b/src/mame/includes/tnzs.h
@@ -1,6 +1,11 @@
 // license:BSD-3-Clause
 // copyright-holders:Luca Elia, Mirko Buffoni, Takahiro Nogi
 
+#pragma once
+
+#ifndef MAME_INCLUDES_TNZS_H
+#define MAME_INCLUDES_TNZS_H
+
 #include "sound/dac.h"
 #include "sound/samples.h"
 #include "video/seta001.h"
@@ -10,77 +15,128 @@
 
 #define MAX_SAMPLES 0x2f        /* max samples */
 
-enum
-{
-	MCU_NONE_INSECTX = 0,
-	MCU_NONE_KAGEKI,
-	MCU_NONE_TNZSB,
-	MCU_NONE_KABUKIZ,
-	MCU_EXTRMATN,
-	MCU_ARKANOID,
-	MCU_PLUMPOP,
-	MCU_DRTOPPEL,
-	MCU_CHUKATAI,
-	MCU_TNZS
-};
-
-class tnzs_state : public driver_device
+class tnzs_base_state : public driver_device
 {
 public:
-	tnzs_state(const machine_config &mconfig, device_type type, const char *tag)
-		: driver_device(mconfig, type, tag),
-		m_maincpu(*this, "maincpu"),
-		m_audiocpu(*this, "audiocpu"),
-		m_subcpu(*this, "sub"),
-		m_mcu(*this, "mcu"),
-		m_seta001(*this, "spritegen"),
-		m_samples(*this, "samples"),
-		m_palette(*this, "palette"),
-		m_soundlatch(*this, "soundlatch"),
-		m_mainbank(*this, "mainbank"),
-		m_subbank(*this, "subbank"),
-		m_audiobank(*this, "audiobank"),
-		m_dswa(*this, "DSWA"),
-		m_dswb(*this, "DSWB"),
-		m_in0(*this, "IN0"),
-		m_in1(*this, "IN1"),
-		m_in2(*this, "IN2"),
-		m_coin1(*this, "COIN1"),
-		m_coin2(*this, "COIN2"),
-		m_an1(*this, "AN1"),
-		m_an2(*this, "AN2")
-		{ }
+	tnzs_base_state(const machine_config &mconfig, device_type type, const char *tag)
+		: driver_device(mconfig, type, tag)
+		, m_maincpu(*this, "maincpu")
+		, m_subcpu(*this, "sub")
+		, m_seta001(*this, "spritegen")
+		, m_palette(*this, "palette")
+		, m_mainbank(*this, "mainbank")
+		, m_subbank(*this, "subbank")
+		, m_an1(*this, "AN1")
+		, m_an2(*this, "AN2")
+	{ }
+
+	virtual void machine_start() override;
+
+	virtual DECLARE_WRITE8_MEMBER(bankswitch1_w);
+
+	DECLARE_WRITE8_MEMBER(ramrom_bankswitch_w);
+
+	uint32_t screen_update_tnzs(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
+	void screen_eof_tnzs(screen_device &screen, bool state);
+
+	DECLARE_READ8_MEMBER(analog_r); // TODO: Move into a subclass
+
+	DECLARE_PALETTE_INIT(prompalette);
 
+protected:
 	/* devices */
 	required_device<cpu_device> m_maincpu;
-	optional_device<cpu_device> m_audiocpu;
 	optional_device<cpu_device> m_subcpu;
-	optional_device<upi41_cpu_device> m_mcu;
 	optional_device<seta001_device> m_seta001;
-	optional_device<samples_device> m_samples;
 	required_device<palette_device> m_palette;
-	optional_device<generic_latch_8_device> m_soundlatch;
-	optional_device<address_map_bank_device> m_mainbank;
-	optional_memory_bank m_subbank; /* optional because of reuse from cchance.c */
-	optional_memory_bank m_audiobank;
-	required_ioport m_dswa;
-	required_ioport m_dswb;
+	optional_device<address_map_bank_device> m_mainbank; /* FIXME: optional because of reuse from cchance.cpp */
+	optional_memory_bank m_subbank; /* FIXME: optional because of reuse from cchance.cpp */
+
+	optional_ioport m_an1; // TODO: Move these into a subclass
+	optional_ioport m_an2;
+
+	/* misc / mcu */
+	int      m_bank2;
+};
+
+class tnzs_mcu_state : public tnzs_base_state
+{
+public:
+	tnzs_mcu_state(const machine_config &mconfig, device_type type, const char *tag, bool lockout_level)
+		: tnzs_base_state(mconfig, type, tag)
+		, m_mcu(*this, "mcu")
+		, m_in0(*this, "IN0")
+		, m_in1(*this, "IN1")
+		, m_in2(*this, "IN2")
+		, m_input_select(0)
+		, m_lockout_level(lockout_level)
+	{ }
+
+	virtual DECLARE_WRITE8_MEMBER(bankswitch1_w) override;
+
+	DECLARE_READ8_MEMBER(mcu_port1_r);
+	DECLARE_READ8_MEMBER(mcu_port2_r);
+	DECLARE_WRITE8_MEMBER(mcu_port2_w );
+	DECLARE_READ8_MEMBER(mcu_r);
+	DECLARE_WRITE8_MEMBER(mcu_w);
+
+protected:
+	required_device<upi41_cpu_device> m_mcu;
+
 	required_ioport m_in0;
 	required_ioport m_in1;
 	required_ioport m_in2;
-	optional_ioport m_coin1;
-	optional_ioport m_coin2;
-	optional_ioport m_an1;
-	optional_ioport m_an2;
-
-	/* sound-related */
-	std::unique_ptr<int16_t[]>    m_sampledata[MAX_SAMPLES];
-	int      m_samplesize[MAX_SAMPLES];
 
-	/* misc / mcu */
-	int      m_kageki_csport_sel;
 	int      m_input_select;
-	int      m_mcu_type;
+	bool     m_lockout_level;
+};
+
+class tnzs_state : public tnzs_mcu_state
+{
+public:
+	tnzs_state(const machine_config &mconfig, device_type type, const char *tag)
+		: tnzs_mcu_state(mconfig, type, tag, true)
+	{ }
+};
+
+class extrmatn_state : public tnzs_mcu_state
+{
+public:
+	extrmatn_state(const machine_config &mconfig, device_type type, const char *tag)
+		: tnzs_mcu_state(mconfig, type, tag, false)
+	{ }
+};
+
+class arknoid2_state : public extrmatn_state
+{
+public:
+	arknoid2_state(const machine_config &mconfig, device_type type, const char *tag)
+		: extrmatn_state(mconfig, type, tag)
+		, m_coin1(*this, "COIN1")
+		, m_coin2(*this, "COIN2")
+		, m_in0(*this, "IN0")
+		, m_in1(*this, "IN1")
+		, m_in2(*this, "IN2")
+	{ }
+
+	virtual void machine_start() override;
+	virtual void machine_reset() override;
+
+	virtual DECLARE_WRITE8_MEMBER(bankswitch1_w) override;
+
+	DECLARE_READ8_MEMBER(mcu_r);
+	DECLARE_WRITE8_MEMBER(mcu_w);
+	INTERRUPT_GEN_MEMBER(mcu_interrupt);
+
+private:
+	required_ioport m_coin1;
+	required_ioport m_coin2;
+	required_ioport m_in0;
+	required_ioport m_in1;
+	required_ioport m_in2;
+
+	void mcu_reset();
+
 	int      m_mcu_initializing;
 	int      m_mcu_coinage_init;
 	int      m_mcu_command;
@@ -91,52 +147,103 @@ public:
 	uint8_t    m_mcu_coins_a;
 	uint8_t    m_mcu_coins_b;
 	uint8_t    m_mcu_credits;
-	int      m_bank2;
 
-	DECLARE_WRITE8_MEMBER(tnzsb_sound_command_w);
-	DECLARE_WRITE8_MEMBER(jpopnics_subbankswitch_w);
-	DECLARE_READ8_MEMBER(tnzs_port1_r);
-	DECLARE_READ8_MEMBER(tnzs_port2_r);
-	DECLARE_WRITE8_MEMBER(tnzs_port2_w);
-	DECLARE_READ8_MEMBER(arknoid2_sh_f000_r);
-	DECLARE_READ8_MEMBER(tnzs_mcu_r);
-	DECLARE_WRITE8_MEMBER(tnzs_mcu_w);
-	DECLARE_WRITE8_MEMBER(tnzs_ramrom_bankswitch_w);
-	DECLARE_WRITE8_MEMBER(tnzs_bankswitch1_w);
-	DECLARE_READ8_MEMBER(mcu_tnzs_r);
-	DECLARE_WRITE8_MEMBER(mcu_tnzs_w);
-	DECLARE_READ8_MEMBER(mcu_arknoid2_r);
-	DECLARE_WRITE8_MEMBER(mcu_arknoid2_w);
-	DECLARE_READ8_MEMBER(mcu_extrmatn_r);
-	DECLARE_WRITE8_MEMBER(mcu_extrmatn_w);
-	DECLARE_READ8_MEMBER(kageki_csport_r);
-	DECLARE_WRITE8_MEMBER(kageki_csport_w);
-	DECLARE_WRITE8_MEMBER(kabukiz_sound_bank_w);
-	DECLARE_WRITE_LINE_MEMBER(irqhandler);
-
-	SAMPLES_START_CB_MEMBER(kageki_init_samples);
-
-	DECLARE_DRIVER_INIT(arknoid2);
-	DECLARE_DRIVER_INIT(extrmatn);
-	DECLARE_DRIVER_INIT(drtoppel);
-	DECLARE_DRIVER_INIT(kabukiz);
-	DECLARE_DRIVER_INIT(plumpop);
-	DECLARE_DRIVER_INIT(insectx);
-	DECLARE_DRIVER_INIT(tnzs);
+	void mcu_handle_coins(int coin);
+};
+
+class kageki_state : public tnzs_base_state
+{
+public:
+	kageki_state(const machine_config &mconfig, device_type type, const char *tag)
+		: tnzs_base_state(mconfig, type, tag)
+		, m_samples(*this, "samples")
+		, m_dswa(*this, "DSWA")
+		, m_dswb(*this, "DSWB")
+		, m_csport_sel(0)
+	{ }
+
+	virtual void machine_start() override;
+	virtual void machine_reset() override;
+
+	virtual DECLARE_WRITE8_MEMBER(bankswitch1_w) override;
+
+	DECLARE_READ8_MEMBER(csport_r);
+	DECLARE_WRITE8_MEMBER(csport_w);
+
+	DECLARE_MACHINE_RESET(kageki);
 	DECLARE_DRIVER_INIT(kageki);
-	DECLARE_DRIVER_INIT(chukatai);
-	DECLARE_DRIVER_INIT(tnzsb);
-	DECLARE_MACHINE_START(tnzs);
-	DECLARE_MACHINE_RESET(tnzs);
-	DECLARE_PALETTE_INIT(arknoid2);
-	DECLARE_MACHINE_START(tnzs_common);
-	DECLARE_MACHINE_RESET(jpopnics);
 
-	uint32_t screen_update_tnzs(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
-	void screen_eof_tnzs(screen_device &screen, bool state);
+	SAMPLES_START_CB_MEMBER(init_samples);
 
-	INTERRUPT_GEN_MEMBER(arknoid2_interrupt);
+private:
+	required_device<samples_device> m_samples;
 
-	void mcu_reset();
-	void mcu_handle_coins(int coin);
+	required_ioport m_dswa;
+	required_ioport m_dswb;
+
+	/* sound-related */
+	std::unique_ptr<int16_t[]>    m_sampledata[MAX_SAMPLES];
+	int      m_samplesize[MAX_SAMPLES];
+
+	int      m_csport_sel;
 };
+
+class jpopnics_state : public tnzs_base_state
+{
+public:
+	jpopnics_state(const machine_config &mconfig, device_type type, const char *tag)
+		: tnzs_base_state(mconfig, type, tag)
+	{ }
+
+	virtual void machine_reset() override;
+
+	DECLARE_WRITE8_MEMBER(subbankswitch_w);
+};
+
+class insectx_state : public tnzs_base_state
+{
+public:
+	insectx_state(const machine_config &mconfig, device_type type, const char *tag)
+		: tnzs_base_state(mconfig, type, tag)
+	{ }
+
+	virtual DECLARE_WRITE8_MEMBER(bankswitch1_w) override;
+};
+
+class tnzsb_state : public tnzs_base_state
+{
+public:
+	tnzsb_state(const machine_config &mconfig, device_type type, const char *tag)
+		: tnzs_base_state(mconfig, type, tag)
+		, m_audiocpu(*this, "audiocpu")
+		, m_soundlatch(*this, "soundlatch")
+	{ }
+
+	DECLARE_WRITE_LINE_MEMBER(ym2203_irqhandler);
+
+	DECLARE_WRITE8_MEMBER(sound_command_w);
+
+	virtual DECLARE_WRITE8_MEMBER(bankswitch1_w) override;
+
+protected:
+	required_device<cpu_device> m_audiocpu;
+	required_device<generic_latch_8_device> m_soundlatch;
+};
+
+class kabukiz_state : public tnzsb_state
+{
+public:
+	kabukiz_state(const machine_config &mconfig, device_type type, const char *tag)
+		: tnzsb_state(mconfig, type, tag)
+		, m_audiobank(*this, "audiobank")
+	{ }
+
+	virtual void machine_start() override;
+
+	DECLARE_WRITE8_MEMBER(sound_bank_w);
+
+protected:
+	required_memory_bank m_audiobank;
+};
+
+#endif // MAME_INCLUDES_TNZS_H
diff --git a/src/mame/includes/toaplan1.h b/src/mame/includes/toaplan1.h
index ff437df..26020a9 100644
--- a/src/mame/includes/toaplan1.h
+++ b/src/mame/includes/toaplan1.h
@@ -39,10 +39,6 @@ public:
 	uint32_t m_dsp_addr_w;
 	uint32_t m_main_ram_seg;
 
-	uint8_t m_vimana_coins[2];
-	uint8_t m_vimana_credits;
-	uint8_t m_vimana_latch;
-
 	std::unique_ptr<uint16_t[]> m_pf4_tilevram16;   /*  ||  Drawn in this order */
 	std::unique_ptr<uint16_t[]> m_pf3_tilevram16;   /*  ||  */
 	std::unique_ptr<uint16_t[]> m_pf2_tilevram16;   /* \||/ */
@@ -84,6 +80,8 @@ public:
 	tilemap_t *m_pf3_tilemap;
 	tilemap_t *m_pf4_tilemap;
 
+
+
 	DECLARE_WRITE16_MEMBER(toaplan1_intenable_w);
 	DECLARE_WRITE16_MEMBER(demonwld_dsp_addrsel_w);
 	DECLARE_READ16_MEMBER(demonwld_dsp_r);
@@ -92,9 +90,6 @@ public:
 	DECLARE_READ_LINE_MEMBER(demonwld_BIO_r);
 	DECLARE_WRITE16_MEMBER(demonwld_dsp_ctrl_w);
 	DECLARE_READ16_MEMBER(samesame_port_6_word_r);
-	DECLARE_READ16_MEMBER(vimana_system_port_r);
-	DECLARE_READ16_MEMBER(vimana_mcu_r);
-	DECLARE_WRITE16_MEMBER(vimana_mcu_w);
 	DECLARE_READ16_MEMBER(toaplan1_shared_r);
 	DECLARE_WRITE16_MEMBER(toaplan1_shared_w);
 	DECLARE_WRITE16_MEMBER(toaplan1_reset_sound_w);
@@ -121,9 +116,19 @@ public:
 	DECLARE_READ16_MEMBER(toaplan1_scroll_regs_r);
 	DECLARE_WRITE16_MEMBER(toaplan1_scroll_regs_w);
 
+	// Fire Shark sound
+	uint8_t m_to_mcu;
+	uint8_t m_cmdavailable;
+
+	DECLARE_READ8_MEMBER(vimana_dswb_invert_r);
+	DECLARE_READ8_MEMBER(vimana_tjump_invert_r);
+	DECLARE_WRITE16_MEMBER(samesame_mcu_w);
+	DECLARE_READ8_MEMBER(samesame_soundlatch_r);
+	DECLARE_WRITE8_MEMBER(samesame_sound_done_w);
+	DECLARE_READ8_MEMBER(samesame_cmdavailable_r);
+
 	DECLARE_DRIVER_INIT(toaplan1);
 	DECLARE_DRIVER_INIT(demonwld);
-	DECLARE_DRIVER_INIT(vimana);
 	TILE_GET_INFO_MEMBER(get_pf1_tile_info);
 	TILE_GET_INFO_MEMBER(get_pf2_tile_info);
 	TILE_GET_INFO_MEMBER(get_pf3_tile_info);
@@ -151,7 +156,6 @@ public:
 	void toaplan1_reset_sound();
 	void toaplan1_driver_savestate();
 	void demonwld_driver_savestate();
-	void vimana_driver_savestate();
 	DECLARE_WRITE_LINE_MEMBER(toaplan1_reset_callback);
 	required_device<m68000_device> m_maincpu;
 	required_device<cpu_device> m_audiocpu;
diff --git a/src/mame/includes/toaplan2.h b/src/mame/includes/toaplan2.h
index 6d75f47..727e5ef 100644
--- a/src/mame/includes/toaplan2.h
+++ b/src/mame/includes/toaplan2.h
@@ -147,6 +147,14 @@ public:
 	DECLARE_VIDEO_START(bgaregga);
 	DECLARE_VIDEO_START(bgareggabl);
 	DECLARE_VIDEO_START(batrider);
+
+	// Teki Paki sound
+	uint8_t m_cmdavailable;
+
+	DECLARE_WRITE16_MEMBER(tekipaki_mcu_w);
+	DECLARE_READ8_MEMBER(tekipaki_soundlatch_r);
+	DECLARE_READ8_MEMBER(tekipaki_cmdavailable_r);
+
 	uint32_t screen_update_toaplan2(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
 	uint32_t screen_update_dogyuun(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
 	uint32_t screen_update_batsugun(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
diff --git a/src/mame/includes/vaportra.h b/src/mame/includes/vaportra.h
index ddd827c..b1341d9 100644
--- a/src/mame/includes/vaportra.h
+++ b/src/mame/includes/vaportra.h
@@ -44,6 +44,8 @@ public:
 	uint16_t    m_priority[2];
 
 	DECLARE_WRITE16_MEMBER(vaportra_sound_w);
+	DECLARE_READ16_MEMBER(irq6_ack_r);
+	DECLARE_WRITE16_MEMBER(irq6_ack_w);
 	DECLARE_READ16_MEMBER(vaportra_control_r);
 	DECLARE_READ8_MEMBER(vaportra_soundlatch_r);
 	DECLARE_WRITE16_MEMBER(vaportra_priority_w);
diff --git a/src/mame/includes/xbox.h b/src/mame/includes/xbox.h
index 141b2be..6bd4a9c 100644
--- a/src/mame/includes/xbox.h
+++ b/src/mame/includes/xbox.h
@@ -115,6 +115,12 @@ public:
 	bool usb_hack_enabled;
 	required_device<cpu_device> m_maincpu;
 	ohci_usb_controller *ohci_usb;
+	static const struct debugger_constants
+	{
+		uint32_t id;
+		uint32_t parameter[8]; // c c c ? ? ? x x
+	} debugp[];
+	const debugger_constants *debugc_bios;
 
 private:
 	void dump_string_command(int ref, int params, const char **param);
@@ -123,6 +129,7 @@ private:
 	void dump_dpc_command(int ref, int params, const char **param);
 	void dump_timer_command(int ref, int params, const char **param);
 	void curthread_command(int ref, int params, const char **param);
+	void threadlist_command(int ref, int params, const char **param);
 	void generate_irq_command(int ref, int params, const char **param);
 	void nv2a_combiners_command(int ref, int params, const char **param);
 	void waitvblank_command(int ref, int params, const char **param);
@@ -131,6 +138,9 @@ private:
 	void vprogdis_command(int ref, int params, const char **param);
 	void help_command(int ref, int params, const char **param);
 	void xbox_debug_commands(int ref, int params, const char **param);
+	int find_bios_index(running_machine &mach);
+	bool find_bios_hash(running_machine &mach, int bios, uint32_t &crc32);
+	void find_debug_params(running_machine &mach);
 };
 
 ADDRESS_MAP_EXTERN(xbox_base_map, 32);
diff --git a/src/mame/includes/chihiro.h b/src/mame/includes/xbox_nv2a.h
similarity index 98%
rename from src/mame/includes/chihiro.h
rename to src/mame/includes/xbox_nv2a.h
index 44f7561..c8f7094 100644
--- a/src/mame/includes/chihiro.h
+++ b/src/mame/includes/xbox_nv2a.h
@@ -358,7 +358,7 @@ public:
 
 	struct nv2avertex_t : public vertex_t
 	{
-		float w;
+		double w;
 	};
 
 	nv2a_renderer(running_machine &machine) : poly_manager<double, nvidia_object_data, 13, 8192>(machine)
@@ -374,7 +374,9 @@ public:
 		objectdata->data = this;
 		combiner.used = 0;
 		enabled_vertex_attributes = 0;
+		primitives_total_count = 0;
 		indexesleft_count = 0;
+		triangles_bfculled = 0;
 		vertex_pipeline = 4;
 		color_mask = 0xffffffff;
 		backface_culling_enabled = false;
@@ -405,6 +407,8 @@ public:
 		limits_rendertarget.set(0, 0, 640, 480);
 		pitch_rendertarget = 0;
 		pitch_depthbuffer = 0;
+		size_rendertarget = 0;
+		size_depthbuffer = 0;
 		log2height_rendertarget = 0;
 		log2width_rendertarget = 0;
 		dilate_rendertarget = 0;
@@ -483,6 +487,7 @@ public:
 	void savestate_items();
 	void compute_supersample_factors(float &horizontal, float &vertical);
 	void compute_limits_rendertarget(uint32_t chanel, uint32_t subchannel);
+	void compute_size_rendertarget(uint32_t chanel, uint32_t subchannel);
 	void read_vertex(address_space & space, offs_t address, vertex_nv &vertex, int attrib);
 	int read_vertices_0x1800(address_space & space, vertex_nv *destination, uint32_t address, int limit);
 	int read_vertices_0x1808(address_space & space, vertex_nv *destination, uint32_t address, int limit);
@@ -490,6 +495,7 @@ public:
 	int read_vertices_0x1818(address_space & space, vertex_nv *destination, uint32_t address, int limit);
 	void convert_vertices_poly(vertex_nv *source, nv2avertex_t *destination, int count);
 	void assemble_primitive(vertex_nv *source, int count, render_delegate &renderspans);
+	int clip_triangle_w(nv2avertex_t *vi[3], nv2avertex_t *vo);
 	uint32_t render_triangle_clipping(const rectangle &cliprect, render_delegate callback, int paramcount, nv2avertex_t &_v1, nv2avertex_t &_v2, nv2avertex_t &_v3);
 	uint32_t render_triangle_culling(const rectangle &cliprect, render_delegate callback, int paramcount, nv2avertex_t &_v1, nv2avertex_t &_v2, nv2avertex_t &_v3);
 	void clear_render_target(int what, uint32_t value);
@@ -520,6 +526,8 @@ public:
 	rectangle limits_rendertarget;
 	uint32_t pitch_rendertarget;
 	uint32_t pitch_depthbuffer;
+	uint32_t size_rendertarget;
+	uint32_t size_depthbuffer;
 	int log2height_rendertarget;
 	int log2width_rendertarget;
 	int dilate_rendertarget;
@@ -563,8 +571,10 @@ public:
 		int rectheight;
 		int rectwidth;
 	} texture[4];
+	uint32_t triangles_bfculled;
 	NV2A_BEGIN_END primitive_type;
 	uint32_t primitives_count;
+	uint32_t primitives_total_count;
 	int indexesleft_count;
 	int indexesleft_first;
 	uint32_t indexesleft[1024]; // vertex indices sent by the software to the 3d accelerator
diff --git a/src/mame/includes/yunsung8.h b/src/mame/includes/yunsung8.h
index 68f292c..94903be 100644
--- a/src/mame/includes/yunsung8.h
+++ b/src/mame/includes/yunsung8.h
@@ -6,6 +6,8 @@
 
 *************************************************************************/
 
+#include "machine/gen_latch.h"
+#include "machine/74157.h"
 #include "sound/msm5205.h"
 
 class yunsung8_state : public driver_device
@@ -14,35 +16,42 @@ public:
 	yunsung8_state(const machine_config &mconfig, device_type type, const char *tag)
 		: driver_device(mconfig, type, tag),
 		m_maincpu(*this, "maincpu"),
-		m_audiocpu(*this, "audiocpu") ,
+		m_audiocpu(*this, "audiocpu"),
 		m_msm(*this, "msm"),
+		m_adpcm_select(*this, "adpcm_select"),
 		m_gfxdecode(*this, "gfxdecode"),
-		m_palette(*this, "palette")  { }
+		m_palette(*this, "palette"),
+		m_soundlatch(*this, "soundlatch")
+	{
+	}
 
 	/* video-related */
-	tilemap_t     *m_tilemap_0;
-	tilemap_t     *m_tilemap_1;
-	uint8_t       *m_videoram_0;
-	uint8_t       *m_videoram_1;
+	tilemap_t     *m_bg_tilemap;
+	tilemap_t     *m_fg_tilemap;
+	uint8_t       *m_bg_vram;
+	uint8_t       *m_fg_vram;
 	int         m_layers_ctrl;
 	int         m_videobank;
 
 	/* misc */
-	int         m_adpcm;
-	int         m_toggle;
+	bool        m_toggle;
 
 	/* devices */
 	required_device<cpu_device> m_maincpu;
 	required_device<cpu_device> m_audiocpu;
 	required_device<msm5205_device> m_msm;
+	required_device<ls157_device> m_adpcm_select;
 	required_device<gfxdecode_device> m_gfxdecode;
 	required_device<palette_device> m_palette;
+	required_device<generic_latch_8_device> m_soundlatch;
 
 	/* memory */
 	uint8_t      m_videoram[0x4000];
 
 	DECLARE_WRITE8_MEMBER(bankswitch_w);
-	DECLARE_WRITE8_MEMBER(adpcm_w);
+	DECLARE_READ8_MEMBER(sound_command_r);
+	DECLARE_WRITE8_MEMBER(sound_command_w);
+	DECLARE_WRITE8_MEMBER(main_irq_ack_w);
 	DECLARE_WRITE8_MEMBER(videobank_w);
 	DECLARE_READ8_MEMBER(videoram_r);
 	DECLARE_WRITE8_MEMBER(videoram_w);
@@ -50,8 +59,8 @@ public:
 	DECLARE_WRITE8_MEMBER(sound_bankswitch_w);
 	DECLARE_WRITE_LINE_MEMBER(adpcm_int);
 
-	TILE_GET_INFO_MEMBER(get_tile_info_0);
-	TILE_GET_INFO_MEMBER(get_tile_info_1);
+	TILE_GET_INFO_MEMBER(get_bg_tile_info);
+	TILE_GET_INFO_MEMBER(get_fg_tile_info);
 
 	virtual void machine_start() override;
 	virtual void machine_reset() override;
diff --git a/src/mame/layout/aristmk5.lay b/src/mame/layout/aristmk5.lay
new file mode 100644
index 0000000..2f48631
--- /dev/null
+++ b/src/mame/layout/aristmk5.lay
@@ -0,0 +1,267 @@
+<?xml version="1.0"?>
+<mamelayout version="2">
+	<element name="CASHOUT">
+		<rect state="1">
+			<color red="1.0" green="1.0" blue="0.0" />
+		</rect>
+		<rect state="0">
+			<color red="0.5" green="0.5" blue="0.0" />
+		</rect>
+		<text string="CASHOUT">
+			<color red="0.0" green="0.0" blue="0.0" />
+			<bounds x="0" y="0.1" width="1" height="0.8" />
+		</text>
+	</element>
+
+	<element name="1LINE">
+		<rect state="1">
+			<color red="1.0" green="1.0" blue="1.0" />
+		</rect>
+		<rect state="0">
+			<color red="0.5" green="0.5" blue="0.5" />
+		</rect>
+		<text string="1 LINE">
+			<color red="0.0" green="0.0" blue="0.0" />
+			<bounds x="0" y="0.1" width="1" height="0.8" />
+		</text>
+	</element>
+
+	<element name="3LINES">
+		<rect state="1">
+			<color red="1.0" green="1.0" blue="1.0" />
+		</rect>
+		<rect state="0">
+			<color red="0.5" green="0.5" blue="0.5" />
+		</rect>
+		<text string="3 LINES">
+			<color red="0.0" green="0.0" blue="0.0" />
+			<bounds x="0" y="0.1" width="1" height="0.8" />
+		</text>
+	</element>
+
+	<element name="5LINES">
+		<rect state="1">
+			<color red="1.0" green="1.0" blue="1.0" />
+		</rect>
+		<rect state="0">
+			<color red="0.5" green="0.5" blue="0.5" />
+		</rect>
+		<text string="5 LINES">
+			<color red="0.0" green="0.0" blue="0.0" />
+			<bounds x="0" y="0.1" width="1" height="0.8" />
+		</text>
+	</element>
+
+	<element name="7LINES">
+		<rect state="1">
+			<color red="1.0" green="1.0" blue="1.0" />
+		</rect>
+		<rect state="0">
+			<color red="0.5" green="0.5" blue="0.5" />
+		</rect>
+		<text string="7 LINES">
+			<color red="0.0" green="0.0" blue="0.0" />
+			<bounds x="0" y="0.1" width="1" height="0.8" />
+		</text>
+	</element>
+
+	<element name="9LINES">
+		<rect state="1">
+			<color red="1.0" green="1.0" blue="1.0" />
+		</rect>
+		<rect state="0">
+			<color red="0.5" green="0.5" blue="0.5" />
+		</rect>
+		<text string="9 LINES">
+			<color red="0.0" green="0.0" blue="0.0" />
+			<bounds x="0" y="0.1" width="1" height="0.8" />
+		</text>
+	</element>
+
+	<element name="GAMBLE">
+		<rect state="1">
+			<color red="0.5" green="0.0" blue="0.7" />
+		</rect>
+		<rect state="0">
+		<color red="0.25" green="0.0" blue="0.35" />
+
+		</rect>
+		<text string="GAMBLE">
+			<color red="0.0" green="0.0" blue="0.0" />
+			<bounds x="0" y="0.1" width="1" height="0.8" />
+		</text>
+	</element>
+
+	<element name="SERVICE">
+		<rect state="1">
+			<color red="0.0" green="1.0" blue="0.0" />
+		</rect>
+		<rect state="0">
+			<color red="0.0" green="0.5" blue="0.0" />
+		</rect>
+		<text string="SERVICE">
+			<color red="0.0" green="0.0" blue="0.0" />
+			<bounds x="0" y="0.1" width="1" height="0.8" />
+		</text>
+	</element>
+
+	<element name="BET1">
+		<rect state="1">
+			<color red="1.0" green="1.0" blue="1.0" />
+		</rect>
+		<rect state="0">
+			<color red="0.5" green="0.5" blue="0.5" />
+		</rect>
+		<text string="BET 1">
+			<color red="0.0" green="0.0" blue="0.0" />
+			<bounds x="0" y="0.1" width="1" height="0.8" />
+		</text>
+	</element>
+
+	<element name="BET2">
+		<rect state="1">
+			<color red="1.0" green="1.0" blue="1.0" />
+		</rect>
+		<rect state="0">
+			<color red="0.5" green="0.5" blue="0.5" />
+		</rect>
+		<text string="BET 2">
+			<color red="0.0" green="0.0" blue="0.0" />
+			<bounds x="0" y="0.1" width="1" height="0.8" />
+		</text>
+	</element>
+
+	<element name="BET3">
+		<rect state="1">
+			<color red="1.0" green="1.0" blue="1.0" />
+		</rect>
+		<rect state="0">
+			<color red="0.5" green="0.5" blue="0.5" />
+		</rect>
+		<text string="BET 3">
+			<color red="0.0" green="0.0" blue="0.0" />
+			<bounds x="0" y="0.1" width="1" height="0.8" />
+		</text>
+	</element>
+
+	<element name="BET5">
+		<rect state="1">
+			<color red="1.0" green="1.0" blue="1.0" />
+		</rect>
+		<rect state="0">
+			<color red="0.5" green="0.5" blue="0.5" />
+		</rect>
+		<text string="BET 5">
+			<color red="0.0" green="0.0" blue="0.0" />
+			<bounds x="0" y="0.1" width="1" height="0.8" />
+		</text>
+	</element>
+
+	<element name="BET10">
+		<rect state="1">
+			<color red="1.0" green="1.0" blue="1.0" />
+		</rect>
+		<rect state="0">
+			<color red="0.5" green="0.5" blue="0.5" />
+		</rect>
+		<text string="BET 10">
+			<color red="0.0" green="0.0" blue="0.0" />
+			<bounds x="0" y="0.1" width="1" height="0.8" />
+		</text>
+	</element>
+
+	<element name="TAKE_WIN">
+		<rect state="1">
+			<color red="1.0" green="0.7" blue="0.0" />
+		</rect>
+		<rect state="0">
+			<color red="0.5" green="0.35" blue="0.0" />
+		</rect>
+		<text string="TAKE WIN">
+			<color red="0.0" green="0.0" blue="0.0" />
+			<bounds x="0" y="0.1" width="1" height="0.8" />
+		</text>
+	</element>
+
+	<element name="WHITELAMP" defstate="0">
+		<disk state="0">
+			<color red="0.2" green="0.2" blue="0.2" />
+		</disk>
+		<disk state="1">
+			<color red="1.0" green="1.0" blue="1.0" />
+		</disk>
+	</element>
+
+	<element name="REDLAMP" defstate="0">
+		<disk state="0">
+			<color red="0.2" green="0.0" blue="0.0" />
+		</disk>
+		<disk state="1">
+			<color red="1.0" green="0.0" blue="0.0" />
+		</disk>
+	</element>
+
+	<view name="Button Lamps">
+		<screen index="0">
+			<bounds left="0" top="0" right="4" bottom="3" />
+		</screen>
+
+		<!-- Buttons lamps -->
+		<bezel name="lamp8" element="CASHOUT" inputtag="P2" inputmask="0x01">
+			<bounds x="0.27" y="3.02" width="0.31" height="0.24" />
+		</bezel>
+		<bezel name="lamp9" element="1LINE" inputtag="P2" inputmask="0x02">
+			<bounds x="0.68" y="3.02" width="0.31" height="0.24" />
+		</bezel>
+		<bezel name="lamp10" element="3LINES" inputtag="P2" inputmask="0x04">
+			<bounds x="1.09" y="3.02" width="0.31" height="0.24" />
+		</bezel>
+		<bezel name="lamp11" element="5LINES" inputtag="P2" inputmask="0x08">
+			<bounds x="1.51" y="3.02" width="0.31" height="0.24" />
+		</bezel>
+		<bezel name="lamp12" element="7LINES" inputtag="P2" inputmask="0x10">
+			<bounds x="1.91" y="3.02" width="0.31" height="0.24" />
+		</bezel>
+		<bezel name="lamp13" element="9LINES" inputtag="P2" inputmask="0x20">
+			<bounds x="2.32" y="3.02" width="0.31" height="0.24" />
+		</bezel>
+		<bezel name="lamp7" element="SERVICE" inputtag="P1" inputmask="0x80">
+			<bounds x="0.27" y="3.28" width="0.31" height="0.24" />
+		</bezel>
+		<bezel name="lamp6" element="BET1" inputtag="P1" inputmask="0x40">
+			<bounds x="0.68" y="3.28" width="0.31" height="0.24" />
+		</bezel>
+		<bezel name="lamp5" element="BET2" inputtag="P1" inputmask="0x20">
+			<bounds x="1.09" y="3.28" width="0.31" height="0.24" />
+		</bezel>
+		<bezel name="lamp4" element="BET3" inputtag="P1" inputmask="0x10">
+			<bounds x="1.51" y="3.28" width="0.31" height="0.24" />
+		</bezel>
+		<bezel name="lamp3" element="BET5" inputtag="P1" inputmask="0x08">
+			<bounds x="1.91" y="3.28" width="0.31" height="0.24" />
+		</bezel>
+		<bezel name="lamp2" element="BET10" inputtag="P1" inputmask="0x04">
+			<bounds x="2.32" y="3.28" width="0.31" height="0.24" />
+		</bezel>
+		<bezel name="lamp0" element="GAMBLE" inputtag="P1" inputmask="0x01">
+			<bounds x="2.73" y="3.28" width="0.31" height="0.24" />
+		</bezel>
+		<bezel name="lamp1" element="TAKE_WIN" inputtag="P1" inputmask="0x02">
+			<bounds x="3.14" y="3.28" width="0.31" height="0.24" />
+		</bezel>
+
+		<!-- Tower lamps -->
+		<bezel name="lamp17" element="WHITELAMP">
+			<bounds x="3.68" y="3.24" width="0.10" height="0.10" />
+		</bezel>
+		<bezel name="lamp16" element="REDLAMP">
+			<bounds x="3.68" y="3.36" width="0.10" height="0.10" />
+		</bezel>
+	</view>
+
+	<view name="Screen">
+		<screen index="0">
+			<bounds left="0" top="0" right="4" bottom="3" />
+		</screen>
+	</view>
+</mamelayout>
diff --git a/src/mame/layout/funjacks.lay b/src/mame/layout/funjacks.lay
index 924c03a..b75a740 100644
--- a/src/mame/layout/funjacks.lay
+++ b/src/mame/layout/funjacks.lay
@@ -10,6 +10,11 @@
 		<disk state="1"><color red="1.0" green="0.2" blue="0.23" /></disk>
 	</element>
 
+	<element name="hl" defstate="0">
+		<text string=" "><color red="0.0" green="0.0" blue="0.0" /></text>
+		<disk state="1"><color red="1.0" green="1.0" blue="1.0" /></disk>
+	</element>
+
 
 <!-- build screen -->
 
@@ -19,15 +24,21 @@
 			<bounds left="0" right="11" top="0" bottom="8" />
 		</bezel>
 
-		<bezel name="lamp30" element="led"><bounds x="0.2" y="0.2" width="1" height="1" /></bezel>
-		<bezel name="lamp31" element="led"><bounds x="9.8" y="0.2" width="1" height="1" /></bezel>
-		<bezel name="lamp21" element="led"><bounds x="4" y="2" width="1" height="1" /></bezel>
-		<bezel name="lamp20" element="led"><bounds x="6" y="2" width="1" height="1" /></bezel>
-		<bezel name="lamp10" element="led"><bounds x="3" y="4" width="1" height="1" /></bezel>
-		<bezel name="lamp0"  element="led"><bounds x="7" y="4" width="1" height="1" /></bezel>
-		<bezel name="lamp11" element="led"><bounds x="4" y="6" width="1" height="1" /></bezel>
-		<bezel name="lamp1"  element="led"><bounds x="6" y="6" width="1" height="1" /></bezel>
-
+		<bezel name="3.0" element="led"><bounds x="0.2" y="0.2" width="1" height="1" /></bezel>
+		<bezel name="3.1" element="led"><bounds x="9.8" y="0.2" width="1" height="1" /></bezel>
+		<bezel name="2.1" element="led"><bounds x="4" y="2" width="1" height="1" /></bezel>
+		<bezel name="2.0" element="led"><bounds x="6" y="2" width="1" height="1" /></bezel>
+		<bezel name="1.0" element="led"><bounds x="3" y="4" width="1" height="1" /></bezel>
+		<bezel name="0.0" element="led"><bounds x="7" y="4" width="1" height="1" /></bezel>
+		<bezel name="1.1" element="led"><bounds x="4" y="6" width="1" height="1" /></bezel>
+		<bezel name="0.1" element="led"><bounds x="6" y="6" width="1" height="1" /></bezel>
+
+		<bezel element="hl" inputtag="IN.2" inputmask="0x10"><bounds x="4" y="2" width="1" height="1" /><color alpha="0.1" /></bezel>
+		<bezel element="hl" inputtag="IN.2" inputmask="0x20"><bounds x="6" y="2" width="1" height="1" /><color alpha="0.1" /></bezel>
+		<bezel element="hl" inputtag="IN.1" inputmask="0x20"><bounds x="3" y="4" width="1" height="1" /><color alpha="0.1" /></bezel>
+		<bezel element="hl" inputtag="IN.0" inputmask="0x20"><bounds x="7" y="4" width="1" height="1" /><color alpha="0.1" /></bezel>
+		<bezel element="hl" inputtag="IN.1" inputmask="0x10"><bounds x="4" y="6" width="1" height="1" /><color alpha="0.1" /></bezel>
+		<bezel element="hl" inputtag="IN.0" inputmask="0x10"><bounds x="6" y="6" width="1" height="1" /><color alpha="0.1" /></bezel>
 
 	</view>
 </mamelayout>
diff --git a/src/mame/layout/funrlgl.lay b/src/mame/layout/funrlgl.lay
index 7af9fb6..27141d3 100644
--- a/src/mame/layout/funrlgl.lay
+++ b/src/mame/layout/funrlgl.lay
@@ -23,22 +23,22 @@
 			<bounds left="-1" right="12" top="-0.2" bottom="12" />
 		</bezel>
 
-		<bezel name="lamp0"  element="ledr"><bounds x="0" y="0" width="1" height="1" /></bezel>
-		<bezel name="lamp10" element="ledr"><bounds x="0" y="2" width="1" height="1" /></bezel>
-		<bezel name="lamp20" element="ledr"><bounds x="0" y="4" width="1" height="1" /></bezel>
-		<bezel name="lamp30" element="ledr"><bounds x="0" y="6" width="1" height="1" /></bezel>
-		<bezel name="lamp2"  element="ledr"><bounds x="0" y="8" width="1" height="1" /></bezel>
-		<bezel name="lamp12" element="ledr"><bounds x="0" y="10" width="1" height="1" /></bezel>
-
-		<bezel name="lamp22" element="ledr"><bounds x="5" y="2" width="1" height="1" /></bezel>
-		<bezel name="lamp33" element="ledg"><bounds x="5" y="4" width="1" height="1" /></bezel>
-
-		<bezel name="lamp1"  element="ledr"><bounds x="10" y="0" width="1" height="1" /></bezel>
-		<bezel name="lamp11" element="ledr"><bounds x="10" y="2" width="1" height="1" /></bezel>
-		<bezel name="lamp21" element="ledr"><bounds x="10" y="4" width="1" height="1" /></bezel>
-		<bezel name="lamp31" element="ledr"><bounds x="10" y="6" width="1" height="1" /></bezel>
-		<bezel name="lamp3"  element="ledr"><bounds x="10" y="8" width="1" height="1" /></bezel>
-		<bezel name="lamp13" element="ledr"><bounds x="10" y="10" width="1" height="1" /></bezel>
+		<bezel name="0.0" element="ledr"><bounds x="0" y="0" width="1" height="1" /></bezel>
+		<bezel name="1.0" element="ledr"><bounds x="0" y="2" width="1" height="1" /></bezel>
+		<bezel name="2.0" element="ledr"><bounds x="0" y="4" width="1" height="1" /></bezel>
+		<bezel name="3.0" element="ledr"><bounds x="0" y="6" width="1" height="1" /></bezel>
+		<bezel name="0.2" element="ledr"><bounds x="0" y="8" width="1" height="1" /></bezel>
+		<bezel name="1.2" element="ledr"><bounds x="0" y="10" width="1" height="1" /></bezel>
+
+		<bezel name="2.2" element="ledr"><bounds x="5" y="2" width="1" height="1" /></bezel>
+		<bezel name="3.3" element="ledg"><bounds x="5" y="4" width="1" height="1" /></bezel>
+
+		<bezel name="0.1" element="ledr"><bounds x="10" y="0" width="1" height="1" /></bezel>
+		<bezel name="1.1" element="ledr"><bounds x="10" y="2" width="1" height="1" /></bezel>
+		<bezel name="2.1" element="ledr"><bounds x="10" y="4" width="1" height="1" /></bezel>
+		<bezel name="3.1" element="ledr"><bounds x="10" y="6" width="1" height="1" /></bezel>
+		<bezel name="0.3" element="ledr"><bounds x="10" y="8" width="1" height="1" /></bezel>
+		<bezel name="1.3" element="ledr"><bounds x="10" y="10" width="1" height="1" /></bezel>
 
 	</view>
 </mamelayout>
diff --git a/src/mame/layout/guab.lay b/src/mame/layout/guab.lay
new file mode 100644
index 0000000..bfbdfee
--- /dev/null
+++ b/src/mame/layout/guab.lay
@@ -0,0 +1,166 @@
+<?xml version="1.0"?>
+
+<mamelayout version="2">
+	<element name="background">
+	</element>
+	<element name="led" defstate="0">
+		<rect state="0">
+			<color red="0" green="0.2" blue="0" />
+		</rect>
+		<rect state="1">
+			<color red="0" green="0.8" blue="0" />
+		</rect>
+	</element>
+	<view name="Debugging Lamps">
+		<bezel element="background">
+			<bounds x="0" y="0" width="800" height="650" />
+		</bezel>
+		<screen index="0">
+			<bounds left="0" top="0" right="800" bottom="600" />
+		</screen>
+		<bezel name="led_0" element="led">
+			<bounds x="10" y="610" width="10" height="10" />
+		</bezel>
+		<bezel name="led_1" element="led">
+			<bounds x="30" y="610" width="10" height="10" />
+		</bezel>
+		<bezel name="led_2" element="led">
+			<bounds x="50" y="610" width="10" height="10" />
+		</bezel>
+		<bezel name="led_3" element="led">
+			<bounds x="70" y="610" width="10" height="10" />
+		</bezel>
+		<bezel name="led_4" element="led">
+			<bounds x="90" y="610" width="10" height="10" />
+		</bezel>
+		<bezel name="led_5" element="led">
+			<bounds x="110" y="610" width="10" height="10" />
+		</bezel>
+		<bezel name="led_6" element="led">
+			<bounds x="130" y="610" width="10" height="10" />
+		</bezel>
+		<bezel name="led_7" element="led">
+			<bounds x="150" y="610" width="10" height="10" />
+		</bezel>
+		<bezel name="led_8" element="led">
+			<bounds x="170" y="610" width="10" height="10" />
+		</bezel>
+		<bezel name="led_9" element="led">
+			<bounds x="190" y="610" width="10" height="10" />
+		</bezel>
+		<bezel name="led_10" element="led">
+			<bounds x="210" y="610" width="10" height="10" />
+		</bezel>
+		<bezel name="led_11" element="led">
+			<bounds x="230" y="610" width="10" height="10" />
+		</bezel>
+		<bezel name="led_12" element="led">
+			<bounds x="250" y="610" width="10" height="10" />
+		</bezel>
+		<bezel name="led_13" element="led">
+			<bounds x="270" y="610" width="10" height="10" />
+		</bezel>
+		<bezel name="led_14" element="led">
+			<bounds x="290" y="610" width="10" height="10" />
+		</bezel>
+		<bezel name="led_15" element="led">
+			<bounds x="310" y="610" width="10" height="10" />
+		</bezel>
+		<bezel name="led_16" element="led">
+			<bounds x="330" y="610" width="10" height="10" />
+		</bezel>
+		<bezel name="led_17" element="led">
+			<bounds x="350" y="610" width="10" height="10" />
+		</bezel>
+		<bezel name="led_18" element="led">
+			<bounds x="370" y="610" width="10" height="10" />
+		</bezel>
+		<bezel name="led_19" element="led">
+			<bounds x="390" y="610" width="10" height="10" />
+		</bezel>
+		<bezel name="led_20" element="led">
+			<bounds x="410" y="610" width="10" height="10" />
+		</bezel>
+		<bezel name="led_21" element="led">
+			<bounds x="430" y="610" width="10" height="10" />
+		</bezel>
+		<bezel name="led_22" element="led">
+			<bounds x="450" y="610" width="10" height="10" />
+		</bezel>
+		<bezel name="led_23" element="led">
+			<bounds x="470" y="610" width="10" height="10" />
+		</bezel>a
+		<bezel name="led_24" element="led">
+			<bounds x="10" y="630" width="10" height="10" />
+		</bezel>
+		<bezel name="led_25" element="led">
+			<bounds x="30" y="630" width="10" height="10" />
+		</bezel>
+		<bezel name="led_26" element="led">
+			<bounds x="50" y="630" width="10" height="10" />
+		</bezel>
+		<bezel name="led_27" element="led">
+			<bounds x="70" y="630" width="10" height="10" />
+		</bezel>
+		<bezel name="led_28" element="led">
+			<bounds x="90" y="630" width="10" height="10" />
+		</bezel>
+		<bezel name="led_29" element="led">
+			<bounds x="110" y="630" width="10" height="10" />
+		</bezel>
+		<bezel name="led_30" element="led">
+			<bounds x="130" y="630" width="10" height="10" />
+		</bezel>
+		<bezel name="led_31" element="led">
+			<bounds x="150" y="630" width="10" height="10" />
+		</bezel>
+		<bezel name="led_32" element="led">
+			<bounds x="170" y="630" width="10" height="10" />
+		</bezel>
+		<bezel name="led_33" element="led">
+			<bounds x="190" y="630" width="10" height="10" />
+		</bezel>
+		<bezel name="led_34" element="led">
+			<bounds x="210" y="630" width="10" height="10" />
+		</bezel>
+		<bezel name="led_35" element="led">
+			<bounds x="230" y="630" width="10" height="10" />
+		</bezel>
+		<bezel name="led_36" element="led">
+			<bounds x="250" y="630" width="10" height="10" />
+		</bezel>
+		<bezel name="led_37" element="led">
+			<bounds x="270" y="630" width="10" height="10" />
+		</bezel>
+		<bezel name="led_38" element="led">
+			<bounds x="290" y="630" width="10" height="10" />
+		</bezel>
+		<bezel name="led_39" element="led">
+			<bounds x="310" y="630" width="10" height="10" />
+		</bezel>
+		<bezel name="led_40" element="led">
+			<bounds x="330" y="630" width="10" height="10" />
+		</bezel>
+		<bezel name="led_41" element="led">
+			<bounds x="350" y="630" width="10" height="10" />
+		</bezel>
+		<bezel name="led_42" element="led">
+			<bounds x="370" y="630" width="10" height="10" />
+		</bezel>
+		<bezel name="led_43" element="led">
+			<bounds x="390" y="630" width="10" height="10" />
+		</bezel>
+		<bezel name="led_44" element="led">
+			<bounds x="410" y="630" width="10" height="10" />
+		</bezel>
+		<bezel name="led_45" element="led">
+			<bounds x="430" y="630" width="10" height="10" />
+		</bezel>
+		<bezel name="led_46" element="led">
+			<bounds x="450" y="630" width="10" height="10" />
+		</bezel>
+		<bezel name="led_47" element="led">
+			<bounds x="470" y="630" width="10" height="10" />
+		</bezel>
+	</view>
+</mamelayout>
diff --git a/src/mame/layout/qkracer.lay b/src/mame/layout/qkracer.lay
new file mode 100644
index 0000000..fe4616c
--- /dev/null
+++ b/src/mame/layout/qkracer.lay
@@ -0,0 +1,63 @@
+<?xml version="1.0"?>
+<mamelayout version="2">
+
+<!-- define elements -->
+
+	<element name="digit" defstate="0">
+		<led7seg><color red="1.0" green="0.3" blue="0.2" /></led7seg>
+	</element>
+
+	<element name="seg_rect" defstate="0">
+		<rect state="1"><color red="1.0" green="0.3" blue="0.2" /></rect>
+		<rect state="0"><color red="0.125490" green="0.035294" blue="0.0235294" /></rect>
+	</element>
+	<element name="seg_x1" defstate="0">
+		<text string="/" state="1"><color red="1.0" green="0.3" blue="0.2" /></text>
+		<text string="/" state="0"><color red="0.125490" green="0.035294" blue="0.0235294" /></text>
+	</element>
+	<element name="seg_x2" defstate="0">
+		<text string="\" state="1"><color red="1.0" green="0.3" blue="0.2" /></text>
+		<text string="\" state="0"><color red="0.125490" green="0.035294" blue="0.0235294" /></text>
+	</element>
+
+	<element name="gled" defstate="0">
+		<disk state="1"><color red="0.2" green="1.0" blue="0.2" /></disk>
+		<disk state="0"><color red="0.04" green="0.2" blue="0.04" /></disk>
+	</element>
+	<element name="text_right">
+		<text string="RIGHT"><color red="0.5" green="0.4" blue="0.3" /></text>
+	</element>
+
+
+<!-- build screen -->
+
+	<view name="Internal Layout">
+		<bounds left="0" right="93.5" top="0" bottom="15" />
+
+		<bezel name="8.a" element="gled"><bounds x="84.5" y="5" width="4.5" height="4.5" /></bezel>
+		<bezel element="text_right"><bounds x="80" y="10" width="14" height="4.5" /></bezel>
+
+		<bezel name="digit0" element="digit"><bounds x="0" y="0" width="10" height="15" /></bezel>
+		<bezel name="digit1" element="digit"><bounds x="10" y="0" width="10" height="15" /></bezel>
+
+		<bezel name="digit3" element="digit"><bounds x="30" y="0" width="10" height="15" /></bezel>
+		<bezel name="digit4" element="digit"><bounds x="40" y="0" width="10" height="15" /></bezel>
+		<bezel name="digit5" element="digit"><bounds x="50" y="3.5" width="10" height="15" /></bezel>
+		<bezel name="digit6" element="digit"><bounds x="60" y="0" width="10" height="15" /></bezel>
+		<bezel name="digit7" element="digit"><bounds x="70" y="0" width="10" height="15" /></bezel>
+
+<!-- math symbols custom digit -->
+
+		<bezel name="2.4" element="seg_rect"><bounds x="21.5" y="7.25" width="7" height="0.5" /></bezel>
+
+		<bezel name="2.0" element="seg_rect"><bounds x="24.75" y="0.9" width="0.5" height="5.75" /></bezel>
+		<bezel name="2.3" element="seg_rect"><bounds x="24.75" y="8.5" width="0.5" height="5.75" /></bezel>
+
+		<bezel name="2.1" element="seg_x1"><bounds x="24" y="-0.5" width="5" height="7.5" /></bezel>
+		<bezel name="2.2" element="seg_x1"><bounds x="21" y="7" width="5" height="7.5" /></bezel>
+
+		<bezel name="2.5" element="seg_x2"><bounds x="21" y="-0.5" width="5" height="7.5" /></bezel>
+		<bezel name="2.6" element="seg_x2"><bounds x="24" y="7" width="5" height="7.5" /></bezel>
+
+	</view>
+</mamelayout>
diff --git a/src/mame/machine/acitya.cpp b/src/mame/machine/acitya.cpp
deleted file mode 100644
index 68b7aec..0000000
--- a/src/mame/machine/acitya.cpp
+++ /dev/null
@@ -1,204 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:David Widel
-/***************************************************************************
-
-  machine.c
-
-Same Epos board as usual(theglobp,beastf,street heat), see theglobp.c for hardware documentation.  This is fairly easy to decrypt since it has consecutive bytes with the same algorithym.  There are 4 different algorithyms.  One consists almost entirely of text, one contains the majority of code and the remaining 2 are not used much and are therefore the most difficult.  It is however difficult to decrypt to rom.  The data for the coin sound is actually program code in a different phase.  [...]
-
-acitya contains a bug with the insurance in blackjack.  It's impossible to collect, so it's likely that acitya is earlier than bwcasino.
-
-I don't think this game is a gambling game.  For one thing there's no real output hardware on a pacman board and the epos daughterboard doesn't contain any either.
-
-David Widel d_widel at hotmail.com
-
-***************************************************************************/
-
-#include "emu.h"
-#include "includes/pacman.h"
-
-
-void pacman_state::acitya_decrypt_rom_8()
-{
-	int oldbyte,inverted_oldbyte,newbyte;
-	int mem;
-	uint8_t *RAM;
-
-	RAM = memregion("maincpu")->base();
-
-
-	for (mem=0;mem<0x4000;mem++)
-	{
-		oldbyte = RAM[mem];
-		inverted_oldbyte = ~oldbyte;
-
-		/*  Note: D2 is inverted and connected to D1, D5 is inverted and
-		    connected to D0.  The other six data bits are converted by a
-		    PAL10H8 driven by the counter. */
-
-		/* Direct inversion */
-		newbyte  = (inverted_oldbyte & 0x80) >> 2;
-		newbyte |= (oldbyte & 0x40) >> 0;
-		newbyte |= (inverted_oldbyte & 0x20) >> 5;
-		newbyte |= (inverted_oldbyte & 0x10) >> 1;
-		newbyte |= (oldbyte & 0x08) << 1;
-		newbyte |= (inverted_oldbyte & 0x04) >> 1;
-		newbyte |= (oldbyte & 0x02) << 6;
-		newbyte |= (inverted_oldbyte & 0x01) << 2;
-
-		RAM[mem + 0x10000] = newbyte;
-	}
-
-	return;
-}
-
-
-void pacman_state::acitya_decrypt_rom_9()
-{
-	int oldbyte,inverted_oldbyte,newbyte;
-	int mem;
-	uint8_t *RAM;
-
-	RAM = memregion("maincpu")->base();
-
-	for (mem=0;mem<0x4000;mem++)
-	{
-		oldbyte = RAM[mem];
-		inverted_oldbyte = ~oldbyte;
-
-		/*  Note: D2 is inverted and connected to D1, D5 is inverted and
-		    connected to D0.  The other six data bits are converted by a
-		    PAL10H8 driven by the counter. */
-
-		/* Direct inversion */
-		newbyte  = (inverted_oldbyte & 0x80) >> 0;
-		newbyte |= (oldbyte & 0x40) >> 0;
-		newbyte |= (inverted_oldbyte & 0x20) >> 5;
-		newbyte |= (oldbyte & 0x10) >> 1;
-		newbyte |= (oldbyte & 0x08) << 1;
-		newbyte |= (inverted_oldbyte & 0x04) >> 1;
-		newbyte |= (inverted_oldbyte & 0x02) << 4;
-		newbyte |= (inverted_oldbyte & 0x01) << 2;
-		RAM[mem + 0x14000] = newbyte;
-	}
-
-	return;
-}
-
-void pacman_state::acitya_decrypt_rom_A()
-{
-	int oldbyte,inverted_oldbyte,newbyte;
-	int mem;
-	uint8_t *RAM;
-
-	RAM = memregion("maincpu")->base();
-
-	for (mem=0;mem<0x4000;mem++)
-	{
-		oldbyte = RAM[mem];
-		inverted_oldbyte = ~oldbyte;
-
-		/*  Note: D2 is inverted and connected to D1, D5 is inverted and
-		    connected to D0.  The other six data bits are converted by a
-		    PAL10H8 driven by the counter. */
-
-		newbyte  = (inverted_oldbyte & 0x80) >> 2;
-		newbyte |= (inverted_oldbyte & 0x40) >> 2;
-		newbyte |= (inverted_oldbyte & 0x20) >> 5;
-		newbyte |= (inverted_oldbyte & 0x10) >> 1;
-
-		newbyte |= (inverted_oldbyte & 0x08) >> 1;
-		newbyte |= (inverted_oldbyte & 0x04) >> 1;
-		newbyte |= (oldbyte & 0x02) << 6;
-		newbyte |= (oldbyte & 0x01) << 6;
-		RAM[mem + 0x18000] = newbyte;
-	}
-
-	return;
-}
-
-void pacman_state::acitya_decrypt_rom_B()
-{
-	int oldbyte,inverted_oldbyte,newbyte;
-	int mem;
-	uint8_t *RAM;
-
-	RAM = memregion("maincpu")->base();
-
-	for (mem=0;mem<0x4000;mem++)
-	{
-		oldbyte = RAM[mem];
-		inverted_oldbyte = ~oldbyte;
-
-		/*  Note: D2 is inverted and connected to D1, D5 is inverted and
-		    connected to D0.  The other six data bits are converted by a
-		    PAL10H8 driven by the counter. */
-
-		/* Direct inversion */
-		newbyte  = (inverted_oldbyte & 0x80) >> 0;
-		newbyte |= (inverted_oldbyte & 0x40) >> 2;
-		newbyte |= (inverted_oldbyte & 0x20) >> 5;
-		newbyte |= (oldbyte & 0x10) >> 1;
-		newbyte |= (inverted_oldbyte & 0x08) >> 1;
-		newbyte |= (inverted_oldbyte & 0x04) >> 1;
-		newbyte |= (inverted_oldbyte & 0x02) << 4;
-		newbyte |= (oldbyte & 0x01) << 6;
-
-
-		RAM[mem + 0x1C000] = newbyte;
-	}
-
-	return;
-}
-
-
-READ8_MEMBER(pacman_state::acitya_decrypt_rom )
-{
-	if (offset & 0x01)
-	{
-		m_counter = (m_counter - 1) & 0x0F;
-	}
-	else
-	{
-		m_counter = (m_counter + 1) & 0x0F;
-	}
-
-	switch(m_counter)
-	{
-		case 0x08:  membank ("bank1")->set_entry (0);        break;
-		case 0x09:  membank ("bank1")->set_entry (1);        break;
-		case 0x0A:  membank ("bank1")->set_entry (2);        break;
-		case 0x0B:  membank ("bank1")->set_entry (3);        break;
-		default:
-			logerror("Invalid counter = %02X\n",m_counter);
-			break;
-	}
-
-	return 0;
-}
-
-
-MACHINE_START_MEMBER(pacman_state,acitya)
-{
-	uint8_t *RAM = memregion("maincpu")->base();
-
-	/* While the PAL supports up to 16 decryption methods, only four
-	    are actually used in the PAL.  Therefore, we'll take a little
-	    memory overhead and decrypt the ROMs using each method in advance. */
-	acitya_decrypt_rom_8();
-	acitya_decrypt_rom_9();
-	acitya_decrypt_rom_A();
-	acitya_decrypt_rom_B();
-
-	membank("bank1")->configure_entries(0, 4, &RAM[0x10000], 0x4000);
-
-	save_item(NAME(m_counter));
-}
-
-
-MACHINE_RESET_MEMBER(pacman_state,acitya)
-{
-	/* The initial state of the counter is 0x0B */
-	m_counter = 0x0B;
-	membank("bank1")->set_entry(3);
-}
diff --git a/src/mame/machine/acitya.h b/src/mame/machine/acitya.h
deleted file mode 100644
index f15a7f4..0000000
--- a/src/mame/machine/acitya.h
+++ /dev/null
@@ -1,2 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:David Widel
diff --git a/src/mame/machine/amiga.cpp b/src/mame/machine/amiga.cpp
index d76ba2b..4b383a4 100644
--- a/src/mame/machine/amiga.cpp
+++ b/src/mame/machine/amiga.cpp
@@ -873,7 +873,7 @@ static uint32_t blit_line(amiga_state *state)
 
 TIMER_CALLBACK_MEMBER( amiga_state::amiga_blitter_proc )
 {
-	amiga_state *state = machine().driver_data<amiga_state>();
+	amiga_state *state = this;
 	uint32_t blitsum = 0;
 
 	/* logging */
@@ -933,15 +933,15 @@ TIMER_CALLBACK_MEMBER( amiga_state::amiga_blitter_proc )
  *
  *************************************/
 
-static void blitter_setup(address_space &space)
+void amiga_state::blitter_setup()
 {
-	amiga_state *state = space.machine().driver_data<amiga_state>();
+	amiga_state *state = this;
 	int ticks, width, height, blittime;
 
 	/* is there another blitting in progress? */
 	if (CUSTOM_REG(REG_DMACON) & 0x4000)
 	{
-		state->logerror("%s - This program is playing tricks with the blitter\n", space.machine().describe_context() );
+		logerror("%s - This program is playing tricks with the blitter\n", machine().describe_context() );
 		return;
 	}
 
@@ -974,7 +974,7 @@ static void blitter_setup(address_space &space)
 	if ( CUSTOM_REG(REG_DMACON) & 0x0400 )
 	{
 		/* simulate the 68k not running while the blit is going */
-		space.device().execute().adjust_icount(-(blittime/2) );
+		m_maincpu->adjust_icount(-(blittime/2) );
 
 		blittime = BLITTER_NASTY_DELAY;
 	}
@@ -987,7 +987,7 @@ static void blitter_setup(address_space &space)
 	CUSTOM_REG(REG_DMACON) |= 0x4000;
 
 	/* set a timer */
-	state->m_blitter_timer->adjust( downcast<cpu_device *>(&space.device())->cycles_to_attotime( blittime ));
+	m_blitter_timer->adjust( m_maincpu->cycles_to_attotime( blittime ));
 }
 
 
@@ -1260,7 +1260,7 @@ READ16_MEMBER( amiga_state::custom_chip_r )
 
 WRITE16_MEMBER( amiga_state::custom_chip_w )
 {
-	amiga_state *state = space.machine().driver_data<amiga_state>();
+	amiga_state *state = this;
 	uint16_t temp;
 	offset &= 0xff;
 
@@ -1349,7 +1349,7 @@ WRITE16_MEMBER( amiga_state::custom_chip_w )
 			CUSTOM_REG(REG_BLTSIZH) = data & 0x3f;
 			if ( CUSTOM_REG(REG_BLTSIZV) == 0 ) CUSTOM_REG(REG_BLTSIZV) = 0x400;
 			if ( CUSTOM_REG(REG_BLTSIZH) == 0 ) CUSTOM_REG(REG_BLTSIZH) = 0x40;
-			blitter_setup(m_maincpu->space(AS_PROGRAM));
+			blitter_setup();
 			break;
 
 		case REG_BLTSIZV:
@@ -1365,7 +1365,7 @@ WRITE16_MEMBER( amiga_state::custom_chip_w )
 			{
 				CUSTOM_REG(REG_BLTSIZH) = data & 0x7ff;
 				if ( CUSTOM_REG(REG_BLTSIZH) == 0 ) CUSTOM_REG(REG_BLTSIZH) = 0x800;
-				blitter_setup(m_maincpu->space(AS_PROGRAM));
+				blitter_setup();
 			}
 			break;
 
@@ -1693,8 +1693,10 @@ void amiga_state::rs232_tx(int state)
 		m_rs232->write_txd(state);
 }
 
-void amiga_state::rx_write(amiga_state *state, int level)
+void amiga_state::rx_write(int level)
 {
+	amiga_state *state = this;
+
 	m_rx_previous = BIT(CUSTOM_REG(REG_SERDATR), 11);
 	CUSTOM_REG(REG_SERDATR) &= ~SERDATR_RXD;
 	CUSTOM_REG(REG_SERDATR) |= level << 11;
@@ -1702,7 +1704,7 @@ void amiga_state::rx_write(amiga_state *state, int level)
 
 WRITE_LINE_MEMBER( amiga_state::rs232_rx_w )
 {
-	rx_write(this, state);
+	rx_write(state);
 
 	// start bit received?
 	if (m_rx_state == 1)
diff --git a/src/mame/machine/apollo.cpp b/src/mame/machine/apollo.cpp
index 5575a5f..6fecfad 100644
--- a/src/mame/machine/apollo.cpp
+++ b/src/mame/machine/apollo.cpp
@@ -1120,7 +1120,6 @@ MACHINE_CONFIG_FRAGMENT( common )
 	MCFG_PIC8259_ADD( APOLLO_PIC2_TAG, WRITELINE(apollo_state,apollo_pic8259_slave_set_int_line), GND, NOOP)
 
 	MCFG_DEVICE_ADD(APOLLO_PTM_TAG, PTM6840, 0)
-	MCFG_PTM6840_INTERNAL_CLOCK(0)
 	MCFG_PTM6840_EXTERNAL_CLOCKS(250000, 125000, 62500)
 	MCFG_PTM6840_IRQ_CB(WRITELINE(apollo_state, apollo_ptm_irq_function))
 	MCFG_DEVICE_ADD("ptmclock", CLOCK, 250000)
diff --git a/src/mame/machine/archimds.cpp b/src/mame/machine/archimds.cpp
index 35c2f74..9d5b469 100644
--- a/src/mame/machine/archimds.cpp
+++ b/src/mame/machine/archimds.cpp
@@ -116,7 +116,7 @@ void archimedes_state::vidc_vblank()
 	archimedes_request_irq_a(ARCHIMEDES_IRQA_VBL);
 
 	// set up for next vbl
-	m_vbl_timer->adjust(m_screen->time_until_pos(m_vidc_regs[0xb4]));
+	m_vbl_timer->adjust(m_screen->time_until_pos(m_vidc_vblank_time));
 }
 
 /* video DMA */
@@ -155,7 +155,7 @@ void archimedes_state::vidc_video_tick()
 
 	if(m_video_dma_on)
 	{
-		m_vid_timer->adjust(m_screen->time_until_pos(m_vidc_regs[0xb4]));
+		m_vid_timer->adjust(m_screen->time_until_pos(m_vidc_vblank_time+1));
 	}
 	else
 		m_vid_timer->adjust(attotime::never);
@@ -204,9 +204,9 @@ void archimedes_state::vidc_audio_tick()
 		56,    48,    40,    32,    24,    16,     8,     0
 	};
 
-	for(ch=0;ch<8;ch++)
+	for(ch=0; ch<8; ch++)
 	{
-		uint8_t ulaw_temp = (space.read_byte(m_vidc_sndstart+m_vidc_sndcur + ch)) ^ 0xff;
+		uint8_t ulaw_temp = (space.read_byte(m_vidc_sndcur + ch)) ^ 0xff;
 
 		ulaw_comp = (ulaw_temp>>1) | ((ulaw_temp&1)<<7);
 
@@ -217,19 +217,24 @@ void archimedes_state::vidc_audio_tick()
 
 	m_vidc_sndcur+=8;
 
-	if (m_vidc_sndcur >= (m_vidc_sndend-m_vidc_sndstart)+0x10)
+	if (m_vidc_sndcur >= m_vidc_sndendcur)
 	{
-		m_vidc_sndcur = 0;
 		archimedes_request_irq_b(ARCHIMEDES_IRQB_SOUND_EMPTY);
 
 		if(!m_audio_dma_on)
 		{
 			m_snd_timer->adjust(attotime::never);
-			for(ch=0;ch<8;ch++)
+			for(ch=0; ch<8; ch++)
 			{
 				m_dac[ch & 7]->write(0);
 			}
 		}
+		else
+		{
+			//printf("Chaining to next: start %x end %x\n", m_vidc_sndstart, m_vidc_sndend);
+			m_vidc_sndcur = m_vidc_sndstart;
+			m_vidc_sndendcur = m_vidc_sndend;
+		}
 	}
 }
 
@@ -260,6 +265,10 @@ void archimedes_state::ioc_timer(int param)
 	// all timers always run
 	a310_set_timer(param);
 
+	// keep FIQ line ASSERTED if there are active requests
+	if (m_ioc_regs[FIQ_STATUS] & m_ioc_regs[FIQ_MASK])
+		archimedes_request_fiq(0);
+
 	// but only timers 0 and 1 generate IRQs
 	switch (param)
 	{
@@ -289,6 +298,9 @@ void archimedes_state::archimedes_reset()
 	m_ioc_regs[IRQ_STATUS_B] = 0x00; //set up IL[1] On
 	m_ioc_regs[FIQ_STATUS] = 0x80;   //set up Force FIQ
 	m_ioc_regs[CONTROL] = 0xff;
+
+	m_vidc_vblank_time = 10000; // set a stupidly high time so it doesn't fire off
+	m_vbl_timer->adjust(attotime::never);
 }
 
 void archimedes_state::archimedes_init()
@@ -494,7 +506,7 @@ bool archimedes_state::check_floppy_ready()
 	}
 
 	if(floppy)
-		return floppy->ready_r();
+		return !floppy->ready_r();
 
 	return false;
 }
@@ -617,7 +629,7 @@ WRITE32_MEMBER( archimedes_state::ioc_ctrl_w )
 			archimedes_request_irq_a((data & 0x80) ? ARCHIMEDES_IRQA_FORCE : 0);
 
 			if(data & 0x08) //set up the VBLANK timer
-				m_vbl_timer->adjust(m_screen->time_until_pos(m_vidc_regs[0xb4]));
+				m_vbl_timer->adjust(m_screen->time_until_pos(m_vidc_vblank_time));
 
 			break;
 
@@ -842,7 +854,7 @@ WRITE32_MEMBER(archimedes_state::archimedes_ioc_w)
 								---- x--- floppy controller reset
 								*/
 								m_fdc->dden_w(BIT(data, 1));
-								if(data & 8)
+								if (!(data & 8))
 									m_fdc->soft_reset();
 								if(data & ~0xa)
 									printf("%02x Latch B\n",data);
@@ -901,7 +913,6 @@ void archimedes_state::vidc_dynamic_res_change()
 		*/
 		if((m_vidc_regs[VIDC_HCR] >= m_vidc_regs[VIDC_HBER]) &&
 			(m_vidc_regs[VIDC_HBER] >= m_vidc_regs[VIDC_HBSR]) &&
-			(m_vidc_regs[VIDC_VCR] >= m_vidc_regs[VIDC_VBER]) &&
 			(m_vidc_regs[VIDC_VBER] >= m_vidc_regs[VIDC_VBSR]))
 		{
 			rectangle visarea;
@@ -912,13 +923,14 @@ void archimedes_state::vidc_dynamic_res_change()
 			visarea.max_x = m_vidc_regs[VIDC_HBER] - m_vidc_regs[VIDC_HBSR] - 1;
 			visarea.max_y = (m_vidc_regs[VIDC_VBER] - m_vidc_regs[VIDC_VBSR]) * (m_vidc_interlace+1);
 
-			//logerror("Configuring: htotal %d vtotal %d border %d x %d display %d x %d\n",
+			m_vidc_vblank_time = m_vidc_regs[VIDC_VBER] * (m_vidc_interlace+1);
+			//logerror("Configuring: htotal %d vtotal %d border %d x %d display origin %d x %d vblank = %d\n",
 			//  m_vidc_regs[VIDC_HCR], m_vidc_regs[VIDC_VCR],
 			//  visarea.max_x, visarea.max_y,
-			//  m_vidc_regs[VIDC_HDER]-m_vidc_regs[VIDC_HDSR],m_vidc_regs[VIDC_VDER]-m_vidc_regs[VIDC_VDSR]+1);
+			//  m_vidc_regs[VIDC_HDER]-m_vidc_regs[VIDC_HDSR],m_vidc_regs[VIDC_VDER]-m_vidc_regs[VIDC_VDSR]+1,
+			//  m_vidc_vblank_time);
 
-			/* FIXME: pixel clock */
-			refresh = HZ_TO_ATTOSECONDS(pixel_rate[m_vidc_pixel_clk]*2) * m_vidc_regs[VIDC_HCR] * m_vidc_regs[VIDC_VCR];
+			refresh = HZ_TO_ATTOSECONDS(pixel_rate[m_vidc_pixel_clk]) * m_vidc_regs[VIDC_HCR] * m_vidc_regs[VIDC_VCR];
 
 			m_screen->configure(m_vidc_regs[VIDC_HCR], m_vidc_regs[VIDC_VCR] * (m_vidc_interlace+1), visarea, refresh);
 		}
@@ -984,6 +996,8 @@ WRITE32_MEMBER(archimedes_state::archimedes_vidc_w)
 			}
 		}
 
+		// update partials
+		machine().first_screen()->update_partial(machine().first_screen()->vpos());
 	}
 	else if (reg >= 0x60 && reg <= 0x7c)
 	{
@@ -1005,7 +1019,7 @@ WRITE32_MEMBER(archimedes_state::archimedes_vidc_w)
 			case VIDC_HCSR: m_vidc_regs[VIDC_HCSR] = ((val >> 13) & 0x7ff) + 6; break;
 //          #define VIDC_HIR        0x9c
 
-			case VIDC_VCR:  m_vidc_regs[VIDC_VCR] = ((val >> 14)<<1)+1; break;
+			case VIDC_VCR:  m_vidc_regs[VIDC_VCR] = ((val >> 14))+1; break;
 //          #define VIDC_VSWR       0xa4
 			case VIDC_VBSR: m_vidc_regs[VIDC_VBSR] = (val >> 14)+1; break;
 			case VIDC_VDSR: m_vidc_regs[VIDC_VDSR] = (val >> 14)+1; break;
@@ -1023,7 +1037,19 @@ WRITE32_MEMBER(archimedes_state::archimedes_vidc_w)
 
 		vidc_dynamic_res_change();
 	}
-	else if(reg == 0xe0)
+	else if (reg == 0xc0)
+	{
+		m_vidc_regs[reg] = val & 0xffff;
+
+		if (m_audio_dma_on)
+		{
+			double sndhz = 1e6 / ((m_vidc_regs[0xc0] & 0xff) + 2);
+			sndhz /= 8.0;
+			m_snd_timer->adjust(attotime::zero, 0, attotime::from_hz(sndhz));
+			//printf("VIDC: sound freq to %d, sndhz = %f\n", (val & 0xff)-2, sndhz);
+		}
+	}
+	else if (reg == 0xe0)
 	{
 		m_vidc_bpp_mode = ((val & 0x0c) >> 2);
 		m_vidc_interlace = ((val & 0x40) >> 6);
@@ -1099,19 +1125,20 @@ WRITE32_MEMBER(archimedes_state::archimedes_memc_w)
 				if ((data>>10)&1)
 				{
 					m_vidc_vidcur = 0;
-					m_vid_timer->adjust(m_screen->time_until_pos(m_vidc_regs[0xb4]));
+					m_vid_timer->adjust(m_screen->time_until_pos(m_vidc_vblank_time+1));
 				}
 
-				if ((data>>11)&1)
+				if ((data>>11) & 1)
 				{
-					double sndhz;
-
-					/* FIXME: is the frequency correct? */
-					sndhz = (250000.0 / 2) / (double)((m_vidc_regs[0xc0]&0xff)+2);
-
-					printf("MEMC: Starting audio DMA at %f Hz, buffer from %x to %x\n", sndhz, m_vidc_sndstart, m_vidc_sndend);
+					//printf("MEMC: Starting audio DMA at %d uSec, buffer from %x to %x\n", ((m_vidc_regs[0xc0]&0xff)-2)*8, m_vidc_sndstart, m_vidc_sndend);
 
+					double sndhz = 1e6 / ((m_vidc_regs[0xc0] & 0xff) + 2);
+					sndhz /= 8.0;
 					m_snd_timer->adjust(attotime::zero, 0, attotime::from_hz(sndhz));
+					//printf("MEMC: audio DMA start, sound freq %d, sndhz = %f\n", (m_vidc_regs[0xc0] & 0xff)-2, sndhz);
+
+					m_vidc_sndcur = m_vidc_sndstart;
+					m_vidc_sndendcur = m_vidc_sndend;
 				}
 
 				break;
diff --git a/src/mame/machine/at.cpp b/src/mame/machine/at.cpp
index 21f0ac4..56d1293 100644
--- a/src/mame/machine/at.cpp
+++ b/src/mame/machine/at.cpp
@@ -47,7 +47,6 @@ void at_mb_device::device_start()
 MACHINE_CONFIG_FRAGMENT( at_softlists )
 	/* software lists */
 	MCFG_SOFTWARE_LIST_ADD("pc_disk_list","ibm5150")
-	MCFG_SOFTWARE_LIST_ADD("xt_disk_list","ibm5160_flop")
 	MCFG_SOFTWARE_LIST_ADD("at_disk_list","ibm5170")
 	MCFG_SOFTWARE_LIST_ADD("at_cdrom_list","ibm5170_cdrom")
 MACHINE_CONFIG_END
diff --git a/src/mame/machine/beezer.cpp b/src/mame/machine/beezer.cpp
deleted file mode 100644
index 55fb06f..0000000
--- a/src/mame/machine/beezer.cpp
+++ /dev/null
@@ -1,144 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Mathis Rosenhauer
-#include "emu.h"
-#include "cpu/m6809/m6809.h"
-#include "machine/6522via.h"
-#include "includes/beezer.h"
-
-
-
-/* VIA 0 (aka "PPCNP74", U6 @1C on schematics)
-    enabled at CE00-CFFF of main m6809 cpu when bankswitch is set to 0
-    port A:
-        bit 7: input, X from banking latch (d3 of banking register)
-        bit 6: input, Y from banking latch (d4 of banking register)
-        bit 5: input, Z from banking latch (d5 of banking register)
-        bit 4: N/C
-        bit 3: output, /RESET for audio subcpu
-        bit 2: output, /ENABLE for LS139 at 2H for reading control and dipswitch inputs to pbus
-        bit 1: output, MSb of selector for inputs to pbus
-        bit 0: output, LSb of "
-    port B:
-        bits 7-0: input/output: pbus
-    port C:
-        CA1: N/C
-        CA2: input: "TDISP" (one of the higher bits in the video line counter, a mirror of the D5 bit from beezer_line_r), done in /video/beezer.c
-        CB1: ASH1 to via 1
-        CB2: ASH2 to via 1
-    /IRQ: to main m6809 cpu
-    /RES: from main reset generator/watchdog/button
-
-    TODO: find a better way to attach ca2 read to beezer_line_r
-    */
-
-/* VIA 1 (U18 @3C on schematics)
-    port A:
-        bits 7-0: input/output: pbus
-    port B:
-        bit 7: output: TIMER1 OUT (used to gate NOISE (see below) to clock channel 1 of 6840, plus acts as channel 0 by itself)
-        bit 6: input: NOISE (from mm5837 14-bit LFSR, which also connects to clock above)
-        bit 5: output?: N/C
-        bit 4: output?: FMSEL1 (does not appear elsewhere on schematics! what does this do? needs tracing) - always 0?
-        bit 3: output?: FMSEL0 (does not appear elsewhere on schematics! what does this do? needs tracing) - always 0?
-        bit 2: output?: AM (does not appear elsewhere on schematics! what does this do? needs tracing) - always 0?
-        bit 1: output: FM or AM (appears to control some sort of suppression or filtering change of the post-DAC amplifier when enabled, only during the TIMER1 OUT time-slot of the multiplexer, see page 1B 3-3 of schematics) - always 0? why is there a special circuit for it?
-        bit 0: output?: DMOD DISABLE (does not appear elsewhere on schematics! what does this do? needs tracing) - on startup is 0, turns to 1 and stays that way?
-    port C:
-        CA1: AHS2 from via 0 (are these two switched?)
-        CA2: AHS1 from via 0 "
-        CB1: ??put: DMOD CLR (does not appear elsewhere on schematics! what does this do? needs tracing)
-        CB2: ??put: DMOD DATA (does not appear elsewhere on schematics! what does this do? needs tracing)
-    /IRQ: to audio/sub m6809 cpu
-    /RES: from audio reset bit of via 0
-
-    TODO: the entirety of port B, much needs tracing
-    TODO: ports CB1 and CB2, need tracing; ports CA1 and CA2 could use verify as well
-    */
-
-READ8_MEMBER(beezer_state::b_via_0_pa_r)
-{
-	return (m_banklatch&0x38)<<2; // return X,Y,Z bits TODO: the Z bit connects somewhere else... where?
-}
-
-READ8_MEMBER(beezer_state::b_via_0_pb_r)
-{
-	return m_pbus;
-}
-
-WRITE8_MEMBER(beezer_state::b_via_0_pa_w)
-{
-	if ((data & 0x08) == 0)
-		m_audiocpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
-	else
-		m_audiocpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
-
-	if ((data & 0x04) == 0)
-	{
-		switch (data & 0x03)
-		{
-		case 0:
-			m_pbus = ioport("IN0")->read();
-			break;
-		case 1:
-			m_pbus = ioport("IN1")->read() | (ioport("IN2")->read() << 4);
-			break;
-		case 2:
-			m_pbus = ioport("DSWB")->read();
-			break;
-		case 3:
-			m_pbus = ioport("DSWA")->read(); // Technically DSWA isn't populated on the board and is pulled to 0xFF with resistor pack, but there IS a DSWA port in the driver so we may as well use it.
-			break;
-		}
-	}
-}
-
-WRITE8_MEMBER(beezer_state::b_via_0_pb_w)
-{
-	m_pbus = data;
-}
-
-READ8_MEMBER(beezer_state::b_via_1_pa_r)
-{
-	return m_pbus;
-}
-
-READ8_MEMBER(beezer_state::b_via_1_pb_r)
-{
-	return 0x1F | (m_custom->noise_r(space, 0)?0x40:0);
-}
-
-WRITE8_MEMBER(beezer_state::b_via_1_pa_w)
-{
-	m_pbus = data;
-}
-
-WRITE8_MEMBER(beezer_state::b_via_1_pb_w)
-{
-	m_custom->timer1_w(space, 0, data&0x80);
-	//if ((data&0x1f) != 0x01)
-	//  popmessage("via1 pb low write of 0x%02x is not supported! contact mamedev!", data&0x1f);
-}
-
-DRIVER_INIT_MEMBER(beezer_state,beezer)
-{
-	m_pbus = 0;
-	m_banklatch = 0;
-}
-
-WRITE8_MEMBER(beezer_state::beezer_bankswitch_w)
-{
-	m_banklatch = data&0x3f; // latched 'x,y,z' plus bank bits in ls174 @ 4H
-	if ((data & 0x07) == 0)
-	{
-		via6522_device *via_0 = machine().device<via6522_device>("via6522_0");
-		space.install_write_handler(0xc600, 0xc7ff, write8_delegate(FUNC(watchdog_timer_device::reset_w),&*m_watchdog));
-		space.install_write_handler(0xc800, 0xc9ff, write8_delegate(FUNC(beezer_state::beezer_map_w),this));
-		space.install_read_handler(0xca00, 0xcbff, read8_delegate(FUNC(beezer_state::beezer_line_r),this));
-		space.install_readwrite_handler(0xce00, 0xcfff, read8_delegate(FUNC(via6522_device::read), via_0), write8_delegate(FUNC(via6522_device::write), via_0));
-	}
-	else
-	{
-		uint8_t *rom = memregion("maincpu")->base() + 0x10000;
-		space.install_ram(0xc000, 0xcfff, rom + (data & 0x07) * 0x2000 + ((data & 0x08) ? 0x1000: 0));
-	}
-}
diff --git a/src/mame/machine/bublbobl.cpp b/src/mame/machine/bublbobl.cpp
index b4ae180..76a76af 100644
--- a/src/mame/machine/bublbobl.cpp
+++ b/src/mame/machine/bublbobl.cpp
@@ -57,29 +57,104 @@ WRITE8_MEMBER(bublbobl_state::bublbobl_nmitrigger_w)
 }
 
 
-static const uint8_t tokio_prot_data[] =
-{
-	0x6c,
-	0x7f,0x5f,0x7f,0x6f,0x5f,0x77,0x5f,0x7f,0x5f,0x7f,0x5f,0x7f,0x5b,0x7f,0x5f,0x7f,
-	0x5f,0x77,0x59,0x7f,0x5e,0x7e,0x5f,0x6d,0x57,0x7f,0x5d,0x7d,0x5f,0x7e,0x5f,0x7f,
-	0x5d,0x7d,0x5f,0x7e,0x5e,0x79,0x5f,0x7f,0x5f,0x7f,0x5d,0x7f,0x5f,0x7b,0x5d,0x7e,
-	0x5f,0x7f,0x5d,0x7d,0x5f,0x7e,0x5e,0x7e,0x5f,0x7d,0x5f,0x7f,0x5f,0x7e,0x7f,0x5f,
-	0x01,0x00,0x02,0x01,0x01,0x01,0x03,0x00,0x05,0x02,0x04,0x01,0x03,0x00,0x05,0x01,
-	0x02,0x03,0x00,0x04,0x04,0x01,0x02,0x00,0x05,0x03,0x02,0x01,0x04,0x05,0x00,0x03,
-	0x00,0x05,0x02,0x01,0x03,0x04,0x05,0x00,0x01,0x04,0x04,0x02,0x01,0x04,0x01,0x00,
-	0x03,0x01,0x02,0x05,0x00,0x03,0x00,0x01,0x02,0x00,0x03,0x04,0x00,0x00,0x00,0x00,
-	0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x00,0x00,0x00,0x00,0x01,0x02,0x00,0x00,0x00,
-	0x01,0x02,0x01,0x00,0x00,0x00,0x02,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x01,
-	0x00,0x00,0x00,0x00,0x02,0x00,0x01,0x02,0x00,0x01,0x01,0x00,0x00,0x02,0x01,0x00,
-	0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x01
-};
+
+CUSTOM_INPUT_MEMBER(bublbobl_state::tokio_mcu_sent_r)
+{
+	if (m_mcu_sent) return 0;
+	else return 1;
+}
+
+CUSTOM_INPUT_MEMBER(bublbobl_state::tokio_main_sent_r)
+{
+	if (m_main_sent) return 0;
+	else return 1;
+}
+
 
 READ8_MEMBER(bublbobl_state::tokio_mcu_r)
 {
-	m_tokio_prot_count %= sizeof(tokio_prot_data);
-	return tokio_prot_data[m_tokio_prot_count++];
+	if (!m_mcu)
+		return 0x00;
+
+	m_mcu_sent = false;
+
+//  printf("%s: tokio_mcu_r %02x\n", space.machine().describe_context(), m_from_mcu);
+
+	return m_from_mcu;
+}
+
+WRITE8_MEMBER(bublbobl_state::tokio_mcu_w)
+{
+	if (!m_mcu)
+		return;
+
+//  printf("%s: tokio_mcu_w %02x\n", space.machine().describe_context(), data);
+
+	m_from_main = data;
+	m_main_sent = true;
+	m_mcu->set_input_line(0, ASSERT_LINE);
+
+}
+
+
+READ8_MEMBER(bublbobl_state::tokio_mcu_porta_r)
+{
+//  printf("tokio_mcu_porta_r\n");
+	return m_to_mcu_latch;
+}
+
+WRITE8_MEMBER(bublbobl_state::tokio_mcu_porta_w)
+{
+//  printf("tokio_mcu_porta_w %02x\n", data);
+	m_from_mcu_latch = data;
+}
+
+
+READ8_MEMBER(bublbobl_state::tokio_mcu_portc_r)
+{
+	uint8_t ret = 0;
+
+	if (!m_main_sent)
+		ret |= 0x01;
+	if (m_mcu_sent)
+		ret |= 0x02;
+
+	ret ^= 0x3; // inverted logic compared to tigerh
+
+//  printf("%s: tokio_mcu_portc_r %02x\n", space.machine().describe_context(), ret);
+
+	return ret;
+}
+
+
+WRITE8_MEMBER(bublbobl_state::tokio_mcu_portb_w)
+{
+//  printf("tokio_mcu_portb_w %02x\n", data);
+
+	if ((mem_mask & 0x02) && (~data & 0x02) && (m_old_portB & 0x02))
+	{
+		if (m_main_sent)
+			m_mcu->set_input_line(0, CLEAR_LINE);
+
+		m_to_mcu_latch = m_from_main;
+		m_main_sent = false;
+	}
+	if ((mem_mask & 0x04) && (data & 0x04) && (~m_old_portB & 0x04))
+	{
+		m_from_mcu = m_from_mcu_latch;
+		m_mcu_sent = true;
+	//  printf("sent %02x\n", m_from_mcu);
+	}
+
+	m_old_portB = data;
+
 }
 
+
+
+
+
+
 READ8_MEMBER(bublbobl_state::tokiob_mcu_r)
 {
 	return 0xbf; /* ad-hoc value set to pass initial testing */
diff --git a/src/mame/machine/cedar_magnet_sound.cpp b/src/mame/machine/cedar_magnet_sound.cpp
index 37132fb..d289c1a 100644
--- a/src/mame/machine/cedar_magnet_sound.cpp
+++ b/src/mame/machine/cedar_magnet_sound.cpp
@@ -2,12 +2,14 @@
 // copyright-holders:David Haywood
 
 /*
-   how should the ctcs hook up properly?
+   This is very similar to the ZSU1 Sound Control Unit, also manufactured by
+   EFO SA and used in the Playmatic pinballs Skill Flight and Phantom Ship;
+   the emulation here is influenced by available schematics for that board.
 
    irq vectors
 
-   0xe6 - from ctc0? (would need vector of e0?) probably used to drive MSM5205
-   0xee - from ctc0? (would need vector of e8?) ^^
+   0xe6 - from ctc0 channel 3 (vector = E0) used to drive MSM5205 through FIFO
+   0xee - from ctc0 channel 3 (vector = E8) ^^
    0xf6 - drive AY (once per frame?) triggered by ctc1 channel 3? (sets vector to f0, f6 = channel3?)
    0xff - read sound latch (triggered by write from master board)
 
@@ -29,7 +31,9 @@ extern const device_type CEDAR_MAGNET_SOUND = &device_creator<cedar_magnet_sound
 cedar_magnet_sound_device::cedar_magnet_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
 	: cedar_magnet_board_device(mconfig, CEDAR_MAGNET_SOUND, "Cedar Sound", tag, owner, clock, "cedmag_sound", __FILE__),
 	m_ctc0(*this, "ctc0"),
-	m_ctc1(*this, "ctc1")
+	m_ctc1(*this, "ctc1"),
+	m_fifo(*this, "fifo"),
+	m_adpcm(*this, "adpcm")
 {
 }
 
@@ -58,7 +62,7 @@ static ADDRESS_MAP_START( cedar_magnet_sound_io, AS_IO, 8, cedar_magnet_sound_de
 	AM_RANGE(0x00, 0x03) AM_DEVREADWRITE("ctc0", z80ctc_device, read, write)
 	AM_RANGE(0x04, 0x07) AM_DEVREADWRITE("ctc1", z80ctc_device, read, write)
 
-	AM_RANGE(0x08, 0x08) AM_WRITE(adpcm_latch_w)
+	AM_RANGE(0x08, 0x08) AM_WRITE(adpcm_fifo_w)
 
 	AM_RANGE(0x0c, 0x0c) AM_DEVWRITE("aysnd0", ay8910_device, address_w)
 	AM_RANGE(0x0d, 0x0d) AM_DEVWRITE("aysnd0", ay8910_device, data_w)
@@ -70,16 +74,28 @@ static ADDRESS_MAP_START( cedar_magnet_sound_io, AS_IO, 8, cedar_magnet_sound_de
 
 ADDRESS_MAP_END
 
-WRITE8_MEMBER(cedar_magnet_sound_device::adpcm_latch_w)
+WRITE8_MEMBER(cedar_magnet_sound_device::adpcm_fifo_w)
 {
-	// it writes 8-bits of sample data here, to be fed to the msm 4-bits at a time
-	// probably via other triggers
-	m_adpcm_data = data;
+	// Z80 code first unpacks 8 bytes of ADPCM sample data into nibbles
+	// and, upon receiving interrupt vector E6, fills FIFO at once using OTIR
+	// 4-bit data is shifted out of the FIFO to the MSM5205 by another timer
+	m_fifo->write(data & 0x0f); // only low nibble is used here
+	m_fifo->si_w(1);
+	m_fifo->si_w(0);
+}
+
+WRITE8_MEMBER(cedar_magnet_sound_device::ay0_porta_w)
+{
+	// unknown; 0x80 written on reset
 }
 
 WRITE8_MEMBER(cedar_magnet_sound_device::ay1_porta_w)
 {
-	// unknown but used
+	m_adpcm->reset_w(data & 1);
+	if (data & 1)
+		m_fifo->reset();
+	// D4-D6 likely used to select clock for ctc0 channel 2
+	// other bits probably used to modulate analog sound output
 }
 
 WRITE_LINE_MEMBER(cedar_magnet_sound_device::ctc0_z0_w)
@@ -92,9 +108,6 @@ WRITE_LINE_MEMBER(cedar_magnet_sound_device::ctc0_z1_w)
 //  printf("USED  ctc0_z1_w %d\n", state);
 }
 
-
-// I don't think any of the below are used
-
 WRITE_LINE_MEMBER(cedar_magnet_sound_device::ctc1_z0_w)
 {
 	printf("ctc1_z0_w %d\n", state);
@@ -115,14 +128,9 @@ WRITE_LINE_MEMBER(cedar_magnet_sound_device::ctc0_z2_w)
 	printf("ctc0_z2_w %d\n", state);
 }
 
-WRITE_LINE_MEMBER(cedar_magnet_sound_device::ctc0_int_w)
+WRITE_LINE_MEMBER(cedar_magnet_sound_device::fifo_dor_w)
 {
-	//printf("ctc0_int_w %d\n", state);
-}
-
-WRITE_LINE_MEMBER(cedar_magnet_sound_device::ctc1_int_w)
-{
-
+	// combined with a clock signal and used to drive ctc0 channel 3
 }
 
 #if 0
@@ -158,23 +166,20 @@ INTERRUPT_GEN_MEMBER(cedar_magnet_sound_device::fake_irq)
 }
 
 static MACHINE_CONFIG_FRAGMENT( cedar_magnet_sound )
-	MCFG_CPU_ADD("topcpu", Z80,4000000)
+	MCFG_CPU_ADD("topcpu", Z80, 4000000)
 	MCFG_CPU_PROGRAM_MAP(cedar_magnet_sound_map)
 	MCFG_CPU_IO_MAP(cedar_magnet_sound_io)
 //  MCFG_Z80_DAISY_CHAIN(daisy_chain)
 	MCFG_CPU_PERIODIC_INT_DRIVER(cedar_magnet_sound_device, fake_irq, 4*60)
 
-	MCFG_DEVICE_ADD("ctc0", Z80CTC, 4000000/8 )
+	MCFG_DEVICE_ADD("ctc0", Z80CTC, 4000000)
 //  MCFG_Z80CTC_INTR_CB(INPUTLINE("topcpu", INPUT_LINE_IRQ0))
-	MCFG_Z80CTC_INTR_CB(WRITELINE(cedar_magnet_sound_device, ctc0_int_w))
 	MCFG_Z80CTC_ZC0_CB(WRITELINE(cedar_magnet_sound_device, ctc0_z0_w))
 	MCFG_Z80CTC_ZC1_CB(WRITELINE(cedar_magnet_sound_device, ctc0_z1_w))
 	MCFG_Z80CTC_ZC2_CB(WRITELINE(cedar_magnet_sound_device, ctc0_z2_w))
 
-	MCFG_DEVICE_ADD("ctc1", Z80CTC, 4000000/8 )
+	MCFG_DEVICE_ADD("ctc1", Z80CTC, 4000000)
 //  MCFG_Z80CTC_INTR_CB(INPUTLINE("topcpu", INPUT_LINE_IRQ0))
-//  MCFG_Z80CTC_INTR_CB(DEVWRITELINE("ctc0", z80ctc_device, trg0))
-	MCFG_Z80CTC_INTR_CB(WRITELINE(cedar_magnet_sound_device, ctc1_int_w))
 	MCFG_Z80CTC_ZC0_CB(WRITELINE(cedar_magnet_sound_device, ctc1_z0_w))
 	MCFG_Z80CTC_ZC1_CB(WRITELINE(cedar_magnet_sound_device, ctc1_z1_w))
 	MCFG_Z80CTC_ZC2_CB(WRITELINE(cedar_magnet_sound_device, ctc1_z2_w))
@@ -182,15 +187,19 @@ static MACHINE_CONFIG_FRAGMENT( cedar_magnet_sound )
 	MCFG_SPEAKER_STANDARD_MONO("mono")
 
 	MCFG_SOUND_ADD("aysnd0", AY8910, 4000000/2)
+	MCFG_AY8910_PORT_A_WRITE_CB(WRITE8(cedar_magnet_sound_device, ay0_porta_w))
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.5)
 
 	MCFG_SOUND_ADD("aysnd1", AY8910, 4000000/2)
 	MCFG_AY8910_PORT_A_WRITE_CB(WRITE8(cedar_magnet_sound_device, ay1_porta_w))
 	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.5)
 
-	MCFG_SOUND_ADD("adpcm", MSM5205, 4000000/16)
-	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
+	MCFG_DEVICE_ADD("fifo", HC40105, 0) // HCF40105BE at IC13
+	MCFG_40105_DATA_OUT_READY_CB(WRITELINE(cedar_magnet_sound_device, fifo_dor_w))
+	MCFG_40105_DATA_OUT_CB(DEVWRITELINE("adpcm", msm5205_device, data_w))
 
+	MCFG_SOUND_ADD("adpcm", MSM5205, 4000000/8)
+	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
 MACHINE_CONFIG_END
 
 machine_config_constructor cedar_magnet_sound_device::device_mconfig_additions() const
diff --git a/src/mame/machine/cedar_magnet_sound.h b/src/mame/machine/cedar_magnet_sound.h
index fcd498c..ddc2f65 100644
--- a/src/mame/machine/cedar_magnet_sound.h
+++ b/src/mame/machine/cedar_magnet_sound.h
@@ -9,6 +9,7 @@
 #include "cpu/z80/z80.h"
 #include "cpu/z80/z80daisy.h"
 #include "machine/z80ctc.h"
+#include "machine/40105.h"
 #include "sound/ay8910.h"
 #include "sound/msm5205.h"
 #include "machine/cedar_magnet_board.h"
@@ -27,13 +28,14 @@ public:
 
 	required_device<z80ctc_device> m_ctc0;
 	required_device<z80ctc_device> m_ctc1;
+	required_device<cmos_40105_device> m_fifo;
+	required_device<msm5205_device> m_adpcm;
 
 	DECLARE_READ8_MEMBER(soundlatch_r);
-	DECLARE_WRITE8_MEMBER(adpcm_latch_w);
+	DECLARE_WRITE8_MEMBER(adpcm_fifo_w);
+	DECLARE_WRITE8_MEMBER(ay0_porta_w);
 	DECLARE_WRITE8_MEMBER(ay1_porta_w);
 
-	uint8_t m_adpcm_data;
-
 	void write_command(uint8_t data);
 	uint8_t m_command;
 
@@ -43,8 +45,7 @@ public:
 	DECLARE_WRITE_LINE_MEMBER(ctc0_z0_w);
 	DECLARE_WRITE_LINE_MEMBER(ctc0_z1_w);
 	DECLARE_WRITE_LINE_MEMBER(ctc0_z2_w);
-	DECLARE_WRITE_LINE_MEMBER(ctc0_int_w);
-	DECLARE_WRITE_LINE_MEMBER(ctc1_int_w);
+	DECLARE_WRITE_LINE_MEMBER(fifo_dor_w);
 
 	TIMER_CALLBACK_MEMBER(reset_assert_callback) override;
 
diff --git a/src/mame/machine/epos.cpp b/src/mame/machine/epos.cpp
new file mode 100644
index 0000000..3ead45d
--- /dev/null
+++ b/src/mame/machine/epos.cpp
@@ -0,0 +1,215 @@
+// license:BSD-3-Clause
+// copyright-holders:smf, Mike Balfour, David Widel
+
+#include "emu.h"
+#include "includes/pacman.h"
+
+READ8_MEMBER(pacman_state::epos_decryption_w)
+{
+	if (offset & 0x01)
+	{
+		m_counter = (m_counter - 1) & 0x0F;
+	}
+	else
+	{
+		m_counter = (m_counter + 1) & 0x0F;
+	}
+
+	switch (m_counter)
+	{
+	case 0x08:
+	case 0x09:
+	case 0x0A:
+	case 0x0B:
+		membank("bank1")->set_entry(m_counter & 3);
+		break;
+
+	default:
+		logerror("Invalid counter = %02X\n", m_counter);
+		break;
+	}
+
+	return 0;
+}
+
+static void epos_decrypt_rom(uint8_t *ROM, uint8_t invert, int offset, int *bs)
+{
+	for (int mem = 0; mem < 0x4000; mem++ )
+	{
+		ROM[mem + offset] = BITSWAP8(ROM[mem] ^ invert, bs[0], bs[1], bs[2], bs[3], bs[4], bs[5], bs[6], bs[7]);
+	}
+}
+
+
+/*
+
+The Glob protection description:
+
+The Glob is designed to run on modified Pacman hardware.  It contains
+two graphics ROMs at 5E and 5F, but contains code ROMs on a daughterboard
+similar in concept to Ms. Pacman.  However, these code ROMs are decrypted
+through additional circuitry.  The daughterboard was encased in epoxy.
+
+Here's a description of the protection as best as I can give it.
+
+1)  The decrypted D0 bit fed to the CPU is simply an inversion of the
+D5 bit from the code ROMs.
+2)  The decrypted D1 bit fed to the CPU is simply an inversion of the
+D2 bit from the code ROMs.
+3)  The other 6 data bits are decrypted by a 10H8 PAL.  The PAL also
+takes as input a 4-bit counter.  The counter is incremented and
+decremented as follows:
+- the Z-80 command IN($xx) where xx is an odd number decrements the
+counter; an even number increments the counter.
+Ex:  IN($64) would increment the counter, IN($6B) would decrement
+the counter.
+4)  The PAL output also contains the two ROM enable lines used to enable
+the two encrypted code ROMs.  As long as the system is working
+correctly, these ROMs will always be enabled.
+
+As it so happens, only four counter values are ever used, which is
+fortunate because the PAL only contains signals to enable the ROMs for
+those four counter values.  The valid counter values are $8, $9, $A, and
+$B.  The counter's intial value is $A, which is set by jumpers on the
+daughterboard.  Following is a description of the resulting decryptions
+for these four counter states.
+
+COUNTER       ENCRYPTED   DECRYPTED
+VALUE       VALUE
+
+DDDDDDDD    DDDDDDDD
+76543210    76543210
+
+Counter = 8:  abcdefgh    EAhBDgFC
+Counter = 9:  abcdefgh    FAgeDBFC
+Counter = A:  abcdefgh    EHDBagFC
+Counter = B:  abcdefgh    GHDEaBFC
+
+In the above diagram, capital letters represent inverted bits.  Notice
+that bits D2 and D5 are the same independent of counter state, this is
+because these bits are not decrypted by the PAL.
+
+
+In the code below, all four of these decryption patterns are used to
+decrypt the entire code ROMs before execution.  This is done for speed,
+since we can then just bankswitch between the decrypted code sets on
+each IN($xx) command, as opposed to dynamically decrypting every byte.
+
+- Mike Balfour (mab22 at po.cwru.edu)
+
+*/
+
+MACHINE_START_MEMBER(pacman_state, theglobp)
+{
+	/*  Note: D2 is inverted and connected to D1, D5 is inverted and
+	connected to D0.  The other six data bits are converted by a
+	PAL10H8 driven by the counter. */
+
+	int bs[4][8] = {
+		{ 3,7,0,6,4,1,2,5 },
+		{ 1,7,0,3,4,6,2,5 },
+		{ 3,0,4,6,7,1,2,5 },
+		{ 1,0,4,3,7,6,2,5 },
+	};
+
+	/* While the PAL supports up to 16 decryption methods, only four
+	are actually used in the PAL.  Therefore, we'll take a little
+	memory overhead and decrypt the ROMs using each method in advance. */
+
+	uint8_t *ROM = memregion("maincpu")->base();
+	epos_decrypt_rom(ROM, 0xfc, 0x10000, bs[0]);
+	epos_decrypt_rom(ROM, 0xf6, 0x14000, bs[1]);
+	epos_decrypt_rom(ROM, 0x7d, 0x18000, bs[2]);
+	epos_decrypt_rom(ROM, 0x77, 0x1c000, bs[3]);
+
+	membank("bank1")->configure_entries(0, 4, &ROM[0x10000], 0x4000);
+
+	save_item(NAME(m_counter));
+}
+
+MACHINE_RESET_MEMBER(pacman_state, theglobp)
+{
+	m_counter = 0x0A;
+	membank("bank1")->set_entry(m_counter & 3);
+}
+
+/*
+
+Same Epos board as usual(theglobp,beastf,street heat). This is fairly easy to decrypt since it has consecutive bytes with the same algorithym.  There are 4 different algorithyms.  One consists almost entirely of text, one contains the majority of code and the remaining 2 are not used much and are therefore the most difficult.  It is however difficult to decrypt to rom.  The data for the coin sound is actually program code in a different phase. You need to move the sound tables and add a  [...]
+
+acitya contains a bug with the insurance in blackjack.  It's impossible to collect, so it's likely that acitya is earlier than bwcasino.
+
+I don't think this game is a gambling game.  For one thing there's no real output hardware on a pacman board and the epos daughterboard doesn't contain any either.
+
+David Widel d_widel at hotmail.com
+
+*/
+
+MACHINE_START_MEMBER(pacman_state, acitya)
+{
+	/*  Note: D2 is inverted and connected to D1, D5 is inverted and
+	connected to D0.  The other six data bits are converted by a
+	PAL10H8 driven by the counter. */
+
+	int bs[4][8] = {
+		{ 1,6,7,3,4,0,2,5 },
+		{ 7,6,1,3,4,0,2,5 },
+		{ 1,0,7,6,4,3,2,5 },
+		{ 7,0,1,6,4,3,2,5 },
+	};
+
+	/* While the PAL supports up to 16 decryption methods, only four
+	are actually used in the PAL.  Therefore, we'll take a little
+	memory overhead and decrypt the ROMs using each method in advance. */
+
+	uint8_t *ROM = memregion("maincpu")->base();
+	epos_decrypt_rom(ROM, 0xb5, 0x10000, bs[0]);
+	epos_decrypt_rom(ROM, 0xa7, 0x14000, bs[1]);
+	epos_decrypt_rom(ROM, 0xfc, 0x18000, bs[2]);
+	epos_decrypt_rom(ROM, 0xee, 0x1c000, bs[3]);
+
+	membank("bank1")->configure_entries(0, 4, &ROM[0x10000], 0x4000);
+
+	save_item(NAME(m_counter));
+}
+
+MACHINE_RESET_MEMBER(pacman_state, acitya)
+{
+	m_counter = 0x0B;
+	membank("bank1")->set_entry(m_counter & 3);
+}
+
+
+MACHINE_START_MEMBER(pacman_state, eeekk)
+{
+	/*  Note: D2 is inverted and connected to D1, D5 is inverted and
+	connected to D0.  The other six data bits are converted by a
+	PAL10H8 driven by the counter. */
+
+	int bs[4][8] = {
+		{ 7,6,1,3,0,4,2,5 },
+		{ 7,1,4,3,0,6,2,5 },
+		{ 7,6,1,0,3,4,2,5 },
+		{ 7,1,4,0,3,6,2,5 },
+	};
+
+	/* While the PAL supports up to 16 decryption methods, only four
+	are actually used in the PAL.  Therefore, we'll take a little
+	memory overhead and decrypt the ROMs using each method in advance. */
+
+	uint8_t *ROM = memregion("maincpu")->base();
+	epos_decrypt_rom(ROM, 0xfd, 0x10000, bs[0]);
+	epos_decrypt_rom(ROM, 0xbf, 0x14000, bs[1]);
+	epos_decrypt_rom(ROM, 0x75, 0x18000, bs[2]);
+	epos_decrypt_rom(ROM, 0x37, 0x1c000, bs[3]);
+
+	membank("bank1")->configure_entries(0, 4, &ROM[0x10000], 0x4000);
+
+	save_item(NAME(m_counter));
+}
+
+MACHINE_RESET_MEMBER(pacman_state, eeekk)
+{
+	m_counter = 0x09;
+	membank("bank1")->set_entry(m_counter & 3);
+}
diff --git a/src/mame/machine/theglobp.h b/src/mame/machine/epos.h
similarity index 100%
rename from src/mame/machine/theglobp.h
rename to src/mame/machine/epos.h
diff --git a/src/mame/machine/isbc_208.cpp b/src/mame/machine/isbc_208.cpp
index b4c9abb..e0aba48 100644
--- a/src/mame/machine/isbc_208.cpp
+++ b/src/mame/machine/isbc_208.cpp
@@ -112,6 +112,9 @@ void isbc_208_device::device_reset()
 {
 	m_aux = 0;
 	m_seg = 0;
+	// set from jumper all drives must be same type
+	if(m_fdc->subdevice<floppy_connector>("0")->get_device()->get_form_factor() == floppy_image::FF_8)
+		m_fdc->set_rate(500000);
 }
 
 void isbc_208_device::device_start()
diff --git a/src/mame/machine/iteagle_fpga.cpp b/src/mame/machine/iteagle_fpga.cpp
index 972b243..b36ed16 100644
--- a/src/mame/machine/iteagle_fpga.cpp
+++ b/src/mame/machine/iteagle_fpga.cpp
@@ -10,10 +10,30 @@
 #define LOG_EEPROM          (0)
 #define LOG_PERIPH          (0)
 
+#define AM85C30_TAG "am85c30_0"
+#define COM1_TAG "com1"
+#define COM2_TAG "com2"
+
 const device_type ITEAGLE_FPGA = &device_creator<iteagle_fpga_device>;
 
 MACHINE_CONFIG_FRAGMENT(iteagle_fpga)
 	MCFG_NVRAM_ADD_0FILL("eagle2_rtc")
+	// RS232 serial ports
+	//MCFG_SCC85C30_ADD(AM85C30_TAG, XTAL_7_3728MHz, XTAL_1_8432MHz, 0, XTAL_1_8432MHz, 0)
+	MCFG_SCC85C30_ADD(AM85C30_TAG, XTAL_1_8432MHz, XTAL_1_8432MHz, 0, XTAL_1_8432MHz, 0)
+	MCFG_Z80SCC_OUT_INT_CB(WRITELINE(iteagle_fpga_device, serial_interrupt))
+	MCFG_Z80SCC_OUT_TXDA_CB(DEVWRITELINE(COM2_TAG, rs232_port_device, write_txd))
+	MCFG_Z80SCC_OUT_TXDB_CB(DEVWRITELINE(COM1_TAG, rs232_port_device, write_txd))
+
+	MCFG_RS232_PORT_ADD(COM1_TAG, default_rs232_devices, nullptr)
+	MCFG_RS232_RXD_HANDLER(DEVWRITELINE(AM85C30_TAG, scc85C30_device, rxb_w))
+	MCFG_RS232_DCD_HANDLER(DEVWRITELINE(AM85C30_TAG, scc85C30_device, dcdb_w))
+	MCFG_RS232_CTS_HANDLER(DEVWRITELINE(AM85C30_TAG, scc85C30_device, ctsb_w))
+
+	MCFG_RS232_PORT_ADD(COM2_TAG, default_rs232_devices, nullptr)
+	MCFG_RS232_RXD_HANDLER(DEVWRITELINE(AM85C30_TAG, scc85C30_device, rxa_w))
+	MCFG_RS232_DCD_HANDLER(DEVWRITELINE(AM85C30_TAG, scc85C30_device, dcda_w))
+	MCFG_RS232_CTS_HANDLER(DEVWRITELINE(AM85C30_TAG, scc85C30_device, ctsa_w))
 MACHINE_CONFIG_END
 
 DEVICE_ADDRESS_MAP_START(fpga_map, 32, iteagle_fpga_device)
@@ -30,7 +50,7 @@ ADDRESS_MAP_END
 
 iteagle_fpga_device::iteagle_fpga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
 	: pci_device(mconfig, ITEAGLE_FPGA, "ITEagle FPGA", tag, owner, clock, "iteagle_fpga", __FILE__),
-		m_rtc(*this, "eagle2_rtc"), m_version(0), m_seq_init(0)
+		m_rtc(*this, "eagle2_rtc"), m_scc1(*this, AM85C30_TAG), m_version(0), m_seq_init(0)
 {
 }
 
@@ -90,18 +110,8 @@ void iteagle_fpga_device::device_reset()
 	m_fpga_regs[0x04/4] =  0x00000000;
 	m_prev_reg = 0;
 
-	m_serial_str.clear();
-	m_serial_idx = 0;
-	m_serial_data = false;
-	memset(m_serial_com0, 0, sizeof(m_serial_com0));
-	memset(m_serial_com1, 0, sizeof(m_serial_com1));
-	memset(m_serial_com2, 0, sizeof(m_serial_com2));
-	memset(m_serial_com3, 0, sizeof(m_serial_com3));
-	m_serial_com0[0] = 0x2c;
-	m_serial_com1[0] = 0x2c;
-	m_serial_com2[0] = 0x2c;
-	m_serial_com3[0] = 0x2c;
-	m_serial_rx3.clear();
+	m_serial0_1.reset();
+	m_serial2_3.reset();
 }
 
 void iteagle_fpga_device::update_sequence(uint32_t data)
@@ -177,6 +187,27 @@ void iteagle_fpga_device::device_timer(emu_timer &timer, device_timer_id tid, in
 
 }
 
+WRITE_LINE_MEMBER(iteagle_fpga_device::serial_interrupt)
+{
+	if (LOG_SERIAL) {
+		osd_printf_info("iteagle_fpga_device::serial_interrupt: intr(%i) = %i\n", m_serial_irq_num, state);
+		logerror("serial_interrupt: intr(%i) = %i\n", m_serial_irq_num, state);
+	}
+	m_cpu->set_input_line(m_serial_irq_num, state);
+}
+
+WRITE8_MEMBER(iteagle_fpga_device::serial_rx_w)
+{
+	std::string tmpStr;
+	tmpStr += data;
+	//osd_printf_info("serial_rx_w: %02x\n", data);
+	m_serial0_1.write_rx_str(1, tmpStr);
+	if (0 && m_serial0_1.check_interrupt()) {
+		osd_printf_info("serial_rx_w: %02x\n", data);
+		m_cpu->set_input_line(m_serial_irq_num, ASSERT_LINE);
+	}
+}
+
 READ32_MEMBER( iteagle_fpga_device::fpga_r )
 {
 	uint32_t result = m_fpga_regs[offset];
@@ -189,7 +220,7 @@ READ32_MEMBER( iteagle_fpga_device::fpga_r )
 			break;
 		case 0x04/4:
 			result = (result & 0xFF0FFFFF) | ((machine().root_device().ioport("SW5")->read()&0xf)<<20);
-			if (LOG_FPGA && !ACCESSING_BITS_0_7)
+			if (0 && LOG_FPGA && !ACCESSING_BITS_0_7)
 				logerror("%s:fpga_r offset %04X = %08X & %08X\n", machine().describe_context(), offset*4, result, mem_mask);
 			break;
 		case 0x08/4:
@@ -208,29 +239,45 @@ READ32_MEMBER( iteagle_fpga_device::fpga_r )
 				logerror("%s:fpga_r offset %04X = %08X & %08X\n", machine().describe_context(), offset*4, result, mem_mask);
 			break;
 		case 0x0c/4: //
-			result = (result & 0xFFFF0000) | ((m_serial_com1[m_serial_idx]&0xff)<<8) | (m_serial_com0[m_serial_idx]&0xff);
-			if (ACCESSING_BITS_0_15) {
-				m_serial_data = false;
-				m_serial_idx = 0;
+			result = 0;
+			if (ACCESSING_BITS_0_7) {
+				result |= m_scc1->cb_r(space, offset) << 0;
+				if (LOG_SERIAL) m_serial0_1.read_control(1);
+			}
+			if (ACCESSING_BITS_8_15) {
+				result |= m_scc1->ca_r(space, offset) << 8;
+				if (LOG_SERIAL) m_serial0_1.read_control(0);
+			}
+			if (ACCESSING_BITS_16_23) {
+				result |= m_scc1->db_r(space, offset) <<16;
+				if (LOG_SERIAL) m_serial0_1.read_data(1);
+			}
+			if (ACCESSING_BITS_24_31) {
+				result |= m_scc1->da_r(space, offset) << 24;
+				if (LOG_SERIAL) m_serial0_1.read_data(0);
 			}
-			if (0 && LOG_FPGA)
+			if (1 && LOG_FPGA)
 				logerror("%s:fpga_r offset %04X = %08X & %08X\n", machine().describe_context(), offset*4, result, mem_mask);
 			break;
-		case 0x1c/4: // 1d = modem byte
-			result = (result & 0xFFFF0000) | ((m_serial_com3[m_serial_idx]&0xff)<<8) | (m_serial_com2[m_serial_idx]&0xff);
-			if (ACCESSING_BITS_0_15) {
-				m_serial_data = false;
-				m_serial_idx = 0;
+		case 0x1c/4:
+			result = 0;
+			if (ACCESSING_BITS_0_7) {
+				result |= m_serial2_3.read_control(1) << 0;
+			}
+			if (ACCESSING_BITS_8_15) {
+				result |= m_serial2_3.read_control(0) << 8;
+			}
+			if (ACCESSING_BITS_16_23) {
+				result |= m_serial2_3.read_data(1) << 16;
+				logerror("fpga_r: LEDSIGN read byte: %02X\n", uint8_t(result >> 16));
 			}
 			if (ACCESSING_BITS_24_31) {
-				if (!m_serial_rx3.empty()) {
-					logerror("fpga_r: read byte: %c\n", m_serial_rx3.at(0));
-					result = (result & 0x00FFFFFF) | (m_serial_rx3.at(0)<<24);
-					m_serial_rx3.erase(m_serial_rx3.begin());
-				}
-				if (m_serial_rx3.empty()) {
-					m_serial_com3[0] &= ~0x1;
-					m_serial_com3[3] &= ~0x20;
+				result |= m_serial2_3.read_data(0) << 24;
+				logerror("fpga_r: MODEM read byte: %c\n", (result >> 24) & 0xff);
+			}
+			// Clear interrupts
+			if (ACCESSING_BITS_16_31) {
+				if (!m_serial2_3.check_interrupt()) {
 					m_cpu->set_input_line(m_serial_irq_num, CLEAR_LINE);
 				}
 			}
@@ -293,92 +340,93 @@ WRITE32_MEMBER( iteagle_fpga_device::fpga_w )
 			break;
 		case 0x0c/4:
 			if (ACCESSING_BITS_0_7) {
-				if (!m_serial_data) {
-					m_serial_idx = data&0xf;
-				} else {
-					m_serial_com0[m_serial_idx] = data&0xff;
-					m_serial_idx = 0;
-				}
-				m_serial_data = !m_serial_data;
+				m_scc1->cb_w(space, offset, (data >> 0) & 0xff);
+				if (LOG_SERIAL) m_serial0_1.write_control((data >> 0) & 0xff, 1);
 			}
 			if (ACCESSING_BITS_8_15) {
-				if (!m_serial_data) {
-					m_serial_idx = (data&0x0f00)>>8;
-				} else {
-					m_serial_com1[m_serial_idx] = (data&0xff00)>>8;
-				}
-				m_serial_data = !m_serial_data;
+				m_scc1->ca_w(space, offset, (data >> 8) & 0xff);
+				if (LOG_SERIAL) m_serial0_1.write_control((data >> 8) & 0xff, 0);
 			}
 			if (ACCESSING_BITS_16_23) {
-				if (m_serial_str.size()==0)
-					m_serial_str = "com0: ";
-				m_serial_str += (data>>16)&0xff;
-				if (((data>>16)&0xff)==0xd) {
-					if (LOG_SERIAL) logerror("%s\n", m_serial_str.c_str());
-					osd_printf_debug("%s\n", m_serial_str.c_str());
-					m_serial_str.clear();
+				// Convert 0xd to 0xa
+				uint8_t byte = data >> 16;
+				if (byte==0xd)
+					m_scc1->db_w(space, offset, 0xa);
+				else
+					m_scc1->db_w(space, offset, byte);
+				if (LOG_SERIAL) {
+					m_serial0_1.write_data((data >> 16) & 0xff, 1);
+					if (m_serial0_1.get_tx_str(1).back() == 0xd) {
+						logerror("com0: %s", m_serial0_1.get_tx_str(1).c_str());
+						osd_printf_info("com0: %s\n", m_serial0_1.get_tx_str(1).c_str());
+						m_serial0_1.clear_tx_str(1);
+					}
 				}
 			}
 			if (ACCESSING_BITS_24_31) {
-				if (m_serial_str.size()==0)
-					m_serial_str = "com1: ";
-				m_serial_str += (data>>24)&0xff;
-				if (1) {
-					if (LOG_SERIAL) logerror("%s\n", m_serial_str.c_str());
-					osd_printf_debug("%s\n", m_serial_str.c_str());
-					m_serial_str.clear();
-				}
+				m_scc1->da_w(space, offset, (data >> 24) & 0xff);
+				if (LOG_SERIAL) m_serial0_1.write_data((data >> 24) & 0xff, 0);
 			}
-			if (0 && LOG_FPGA)
+			if (1 && LOG_FPGA)
 					logerror("%s:fpga_w offset %04X = %08X & %08X\n", machine().describe_context(), offset*4, data, mem_mask);
 			break;
 		case 0x1c/4:
 			if (ACCESSING_BITS_0_7) {
-				if (!m_serial_data) {
-					m_serial_idx = data&0xf;
-				} else {
-					m_serial_com2[m_serial_idx] = data&0xff;
-					m_serial_idx = 0;
-				}
-				m_serial_data = !m_serial_data;
+				m_serial2_3.write_control((data >> 0) & 0xff, 1);
 			}
 			if (ACCESSING_BITS_8_15) {
-				if (!m_serial_data) {
-					m_serial_idx = (data&0x0f00)>>8;
-				} else {
-					m_serial_com3[m_serial_idx] = (data&0xff00)>>8;
-				}
-				m_serial_data = !m_serial_data;
+				m_serial2_3.write_control((data >> 8) & 0xff, 0);
 			}
 			if (ACCESSING_BITS_16_23) {
-				if (m_serial_str.size()==0)
-					m_serial_str = "com2: ";
-				m_serial_str += (data>>16)&0xff;
-				if (1) {
-					if (LOG_SERIAL) logerror("%s\n", m_serial_str.c_str());
-					osd_printf_debug("%s\n", m_serial_str.c_str());
-					m_serial_str.clear();
+				int chan = 1;
+				m_serial2_3.write_data((data >> 16) & 0xff, chan);
+				std::string txString = m_serial2_3.get_tx_str(chan);
+				if (txString.length() >= 8) {
+					int length = (uint8_t(txString[4]) << 8) | uint8_t(txString[5]);
+					if (txString.length() >= length) {
+						osd_printf_debug("com2:");
+						if (LOG_SERIAL) logerror("com2:\n");
+						for (int i = 0; i < txString.length(); i++) {
+							if (LOG_SERIAL) logerror(" %02x", uint8_t(txString[i]));
+							osd_printf_debug(" %02x", uint8_t(txString[i]));
+							if ((i + 1) % 16 == 0 || i==length-1) {
+								osd_printf_debug("\n");
+								if (LOG_SERIAL) logerror("\n");
+							}
+						}
+						osd_printf_debug("\n");
+						// Set Sign Response ACK
+						//if (txString[0]==0x01 || txString[0] == 0x23)
+						m_serial2_3.write_rx_str(chan, "\x10");
+						// Clear string
+						m_serial2_3.clear_tx_str(chan);
+						txString.clear();
+					}
 				}
 			}
 			if (ACCESSING_BITS_24_31) {
-				if (m_serial_str.size()==0)
-					m_serial_str = "com3: ";
-				m_serial_str += (data>>24)&0xff;
-				if (((data>>24)&0xff)==0xd) {
-					if (LOG_SERIAL) logerror("%s\n", m_serial_str.c_str());
-					osd_printf_debug("%s\n", m_serial_str.c_str());
-					if (m_serial_str.find("ATI5") != -1)
-						m_serial_rx3 += "OK\r181\r";
-					else if (m_serial_str.find("ATS0?") != -1)
-						m_serial_rx3 += "0\r";
+				int chan = 0;
+				m_serial2_3.write_data((data >> 24) & 0xff, chan);
+				if (m_serial2_3.get_tx_str(chan).back() == 0xd) {
+					if (LOG_SERIAL) logerror("com3: %s\n", m_serial2_3.get_tx_str(chan).c_str());
+					osd_printf_debug("com3: %s\n", m_serial2_3.get_tx_str(chan).c_str());
+					if (m_serial2_3.get_tx_str(chan).find("ATI5") != -1)
+						m_serial2_3.write_rx_str(chan, "OK\r181\r");
+					else if (m_serial2_3.get_tx_str(chan).find("ATS0?") != -1)
+						m_serial2_3.write_rx_str(chan, "0\r");
 					else
-						m_serial_rx3 += "OK\r";
-					m_serial_com3[0] |= 0x1;
-					m_serial_com3[3] = 0x20;
+						m_serial2_3.write_rx_str(chan, "OK\r");
+					m_serial2_3.clear_tx_str(chan);
+				}
+			}
+			// Set interrupt
+			if (ACCESSING_BITS_16_31) {
+				if (m_serial2_3.check_interrupt()) {
 					m_cpu->set_input_line(m_serial_irq_num, ASSERT_LINE);
-					m_serial_str.clear();
 				}
+
 			}
+
 			if (LOG_FPGA)
 					logerror("%s:fpga_w offset %04X = %08X & %08X\n", machine().describe_context(), offset*4, data, mem_mask);
 			break;
@@ -390,6 +438,89 @@ WRITE32_MEMBER( iteagle_fpga_device::fpga_w )
 	}
 }
 //*************************************
+//*  AM85c30 serial controller
+//*************************************
+void iteagle_am85c30::reset(void)
+{
+	memset(m_rr_regs, 0, 0x10 * 2);
+	memset(m_wr_regs, 0, 0x10 * 2);
+	// Set DTS, DCD, and Tx Buf Empty
+	m_rr_regs[0][0] = 0x2c;
+	m_rr_regs[1][0] = 0x2c;
+}
+
+void iteagle_am85c30::write_control(uint8_t data, int channel)
+{
+	uint8_t addr = m_wr_regs[channel][0] & 0xf;
+	m_wr_regs[channel][addr] = data;
+	// Reset address pointer to 0
+	if (addr != 0) {
+		m_wr_regs[channel][0] = 0;
+		// Mirror wr2 to rr2[chan0]
+		m_rr_regs[0][2] = m_wr_regs[channel][2];
+	}
+}
+
+uint8_t iteagle_am85c30::read_control(int channel)
+{
+	uint8_t retVal;
+	uint8_t addr = m_wr_regs[channel][0] & 0xf;
+	retVal = m_rr_regs[channel][addr];
+	// Reset address pointer to 0
+	m_wr_regs[channel][0] = 0;
+	return retVal;
+}
+
+void iteagle_am85c30::write_data(uint8_t data, int channel)
+{
+	if (0 && LOG_SERIAL) printf("chan %i: TX 0x%2X\n", channel, data);
+	m_serial_tx[channel] += data;
+	m_rr_regs[channel][0] |= 0x4; // Tx Buffer Empty
+	// Tx Interrupt
+	if (0 && (m_wr_regs[channel][1] & 0x2)) {
+		// RR3 is shared between A and B
+		m_rr_regs[0][3] |= 0x10 >> (channel * 3);  // 0x10 = ChanA Tx
+		m_rr_regs[1][3] = m_rr_regs[0][3];
+	}
+	// Limit length
+	if (m_serial_tx[channel].size() >= 4000) {
+		if (LOG_SERIAL) printf("%s\n", m_serial_tx[channel].c_str());
+		osd_printf_debug("%s\n", m_serial_tx[channel].c_str());
+		m_serial_tx[channel].clear();
+	}
+}
+
+uint8_t iteagle_am85c30::read_data(int channel)
+{
+	uint8_t retVal = 0;
+	if (!m_serial_rx[channel].empty()) {
+		//logerror("fpga_r: read byte: %c\n", m_serial_rx[channel].at(0));
+		retVal = m_serial_rx[channel].at(0);
+		m_serial_rx[channel].erase(m_serial_rx[channel].begin());
+	}
+	if (m_serial_rx[channel].empty()) {
+		m_rr_regs[channel][0] &= ~0x1;
+		if (m_wr_regs[channel][1] & 0x18) {
+			// RR3 is shared between A and B
+			m_rr_regs[0][3] &= ~(0x20 >> (channel * 3)); // 0x20 = ChanA Rx
+			m_rr_regs[1][3] = m_rr_regs[0][3];
+		}
+	}
+	return retVal;
+}
+
+void iteagle_am85c30::write_rx_str(int channel, std::string resp)
+{
+	m_serial_rx[channel] += resp;
+	m_rr_regs[channel][0] |= 0x1;
+	if (m_wr_regs[channel][1] & 0x18) {
+		// RR3 is shared between A and B
+		m_rr_regs[0][3] |= (0x20 >> (channel * 3)); // 0x20 = ChanA Rx
+		m_rr_regs[1][3] = m_rr_regs[0][3];
+	}
+}
+
+//*************************************
 //*  RTC M48T02
 //*************************************
 READ32_MEMBER( iteagle_fpga_device::rtc_r )
@@ -486,6 +617,7 @@ iteagle_eeprom_device::iteagle_eeprom_device(const machine_config &mconfig, cons
 	// 0x4 = HW Version - 6-8 is GREEN board PCB, 9 is RED board PCB
 	// 0x5 = Serial Num + top byte of 0x4
 	// 0x6 = OperID
+	// 0xd = GT Fore Tournament Board
 	// 0xe = SW Version
 	// 0xf = 0x01 for extra courses
 	// 0x3e = 0x0002 for good nvram
@@ -493,7 +625,7 @@ iteagle_eeprom_device::iteagle_eeprom_device(const machine_config &mconfig, cons
 	m_iteagle_default_eeprom =
 	{ {
 		0xd000,0x0022,0x0000,0x0003,0x1209,0x1111,0x2222,0x1234,
-		0x0000,0x0000,0x0000,0x0000,0xcd00,0x0000,0x0000,0x0001,
+		0x0000,0x0000,0x0000,0x0000,0xcd00,0x0001,0x0000,0x0001,
 		0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
 		0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
 		0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
diff --git a/src/mame/machine/iteagle_fpga.h b/src/mame/machine/iteagle_fpga.h
index 9814f1e..f0cef35 100644
--- a/src/mame/machine/iteagle_fpga.h
+++ b/src/mame/machine/iteagle_fpga.h
@@ -9,6 +9,8 @@
 #include "machine/pci.h"
 #include "machine/nvram.h"
 #include "machine/eepromser.h"
+#include "machine/z80scc.h"
+#include "bus/rs232/rs232.h"
 
 //MCFG_PCI_DEVICE_ADD(_tag, _type, _main_id, _revision, _pclass, _subsystem_id)
 
@@ -29,6 +31,26 @@
 #define MCFG_ITEAGLE_PERIPH_ADD(_tag) \
 	MCFG_PCI_DEVICE_ADD(_tag, ITEAGLE_PERIPH, 0x1080C693, 0x00, 0x060100, 0x00)
 
+// Functional emulation of AMD AM85C30 serial controller
+// Two channels, A & B
+class iteagle_am85c30
+{
+public:
+	void reset(void);
+	void write_control(uint8_t data, int channel);
+	uint8_t read_control(int channel);
+	void write_data(uint8_t data, int channel);
+	uint8_t read_data(int channel);
+	void write_rx_str(int channel, std::string resp);
+	std::string get_tx_str(int channel) { return m_serial_tx[channel]; };
+	void clear_tx_str(int channel) { m_serial_tx[channel].clear(); };
+	bool check_interrupt(void) { return (m_rr_regs[0][3] != 0); };
+private:
+	uint8_t m_rr_regs[2][16];
+	uint8_t m_wr_regs[2][16];
+	std::string m_serial_tx[2];
+	std::string m_serial_rx[2];
+};
 
 class iteagle_fpga_device : public pci_device
 {
@@ -37,11 +59,15 @@ public:
 	virtual machine_config_constructor device_mconfig_additions() const override;
 
 	required_device<nvram_device> m_rtc;
+	required_device<scc85C30_device> m_scc1;
 
 	void set_init_info(int version, int seq_init) {m_version=version; m_seq_init=seq_init;}
 	void set_irq_info(const char *tag, const int irq_num, const int serial_num) {
 		m_cpu_tag = tag; m_irq_num = irq_num; m_serial_irq_num = serial_num;}
 
+	DECLARE_WRITE_LINE_MEMBER(serial_interrupt);
+	DECLARE_WRITE8_MEMBER(serial_rx_w);
+
 protected:
 	virtual void device_start() override;
 	virtual void device_reset() override;
@@ -59,19 +85,14 @@ private:
 	uint32_t m_ram[0x20000 / 4];
 	uint32_t m_prev_reg;
 
-	std::string m_serial_str;
-	std::string m_serial_rx3;
-	uint8_t m_serial_idx;
-	bool  m_serial_data;
-	uint8_t m_serial_com0[0x10];
-	uint8_t m_serial_com1[0x10];
-	uint8_t m_serial_com2[0x10];
-	uint8_t m_serial_com3[0x10];
-
 	uint32_t m_version;
 	uint32_t m_seq_init;
 	uint32_t m_seq;
 	uint32_t m_seq_rem1, m_seq_rem2;
+
+	iteagle_am85c30 m_serial0_1;
+	iteagle_am85c30 m_serial2_3;
+
 	void update_sequence(uint32_t data);
 	void update_sequence_eg1(uint32_t data);
 
diff --git a/src/mame/machine/konamigx.cpp b/src/mame/machine/konamigx.cpp
index 4889cbb..2795765 100644
--- a/src/mame/machine/konamigx.cpp
+++ b/src/mame/machine/konamigx.cpp
@@ -468,6 +468,7 @@ if((data1=obj[0])&0x80000000)\
 void konamigx_state::fantjour_dma_install()
 {
 	save_item(NAME(m_fantjour_dma));
+	save_item(NAME(m_prot_data));
 	m_maincpu->space(AS_PROGRAM).install_write_handler(0xdb0000, 0xdb001f, write32_delegate(FUNC(konamigx_state::fantjour_dma_w),this));
 	memset(m_fantjour_dma, 0, sizeof(m_fantjour_dma));
 }
diff --git a/src/mame/machine/leland.cpp b/src/mame/machine/leland.cpp
index 64eaab3..ae99725 100644
--- a/src/mame/machine/leland.cpp
+++ b/src/mame/machine/leland.cpp
@@ -9,8 +9,6 @@
 ***************************************************************************/
 
 #include "emu.h"
-#include "cpu/i86/i86.h"
-#include "machine/eepromser.h"
 #include "cpu/z80/z80.h"
 #include "includes/leland.h"
 
@@ -322,6 +320,21 @@ MACHINE_START_MEMBER(leland_state,leland)
 
 	/* start scanline interrupts going */
 	m_master_int_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(leland_state::leland_interrupt_callback),this));
+
+	save_item(NAME(m_dac_control));
+	save_item(NAME(m_wcol_enable));
+	save_item(NAME(m_analog_result));
+	save_item(NAME(m_dial_last_input));
+	save_item(NAME(m_dial_last_result));
+	save_item(NAME(m_keycard_shift));
+	save_item(NAME(m_keycard_bit));
+	save_item(NAME(m_keycard_state));
+	save_item(NAME(m_keycard_clock));
+	save_item(NAME(m_keycard_command));
+	save_item(NAME(m_top_board_bank));
+	save_item(NAME(m_sound_port_bank));
+	save_item(NAME(m_alternate_bank));
+	save_item(NAME(m_battery_ram_enable));
 }
 
 
@@ -372,6 +385,15 @@ MACHINE_START_MEMBER(leland_state,ataxx)
 
 	/* start scanline interrupts going */
 	m_master_int_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(leland_state::ataxx_interrupt_callback),this));
+
+	save_item(NAME(m_wcol_enable));
+	save_item(NAME(m_dial_last_input));
+	save_item(NAME(m_dial_last_result));
+	save_item(NAME(m_master_bank));
+	save_item(NAME(m_xrom1_addr));
+	save_item(NAME(m_xrom2_addr));
+	save_item(NAME(m_battery_ram_enable));
+	save_pointer(NAME(m_extra_tram.get()), ATAXX_EXTRA_TRAM_SIZE);
 }
 
 
@@ -381,7 +403,6 @@ MACHINE_RESET_MEMBER(leland_state,ataxx)
 	m_master_int_timer->adjust(m_screen->time_until_pos(8), 8);
 
 	/* initialize the XROM */
-	m_xrom_length = memregion("user1")->bytes();
 	m_xrom_base = memregion("user1")->base();
 	m_xrom1_addr = 0;
 	m_xrom2_addr = 0;
diff --git a/src/mame/machine/m1comm.cpp b/src/mame/machine/m1comm.cpp
index 73ff314..be78985 100644
--- a/src/mame/machine/m1comm.cpp
+++ b/src/mame/machine/m1comm.cpp
@@ -65,7 +65,7 @@ Notes:
 static ADDRESS_MAP_START( m1comm_mem, AS_PROGRAM, 8, m1comm_device )
 	AM_RANGE(0x0000, 0x7fff) AM_ROM
 	AM_RANGE(0x8000, 0x9fff) AM_RAM
-	AM_RANGE(0xC000, 0xffff) AM_READWRITE(share_r, share_w)
+	AM_RANGE(0xc000, 0xffff) AM_READWRITE(share_r, share_w)
 ADDRESS_MAP_END
 
 /*************************************
@@ -73,11 +73,11 @@ ADDRESS_MAP_END
  *************************************/
 static ADDRESS_MAP_START( m1comm_io, AS_IO, 8, m1comm_device )
 	ADDRESS_MAP_GLOBAL_MASK(0xff)
-	AM_RANGE(0x00, 0x1F) AM_READWRITE(dlc_reg_r, dlc_reg_w)
-	AM_RANGE(0x20, 0x2F) AM_READWRITE(dma_reg_r, dma_reg_w)
+	AM_RANGE(0x00, 0x1f) AM_READWRITE(dlc_reg_r, dlc_reg_w)
+	AM_RANGE(0x20, 0x2f) AM_READWRITE(dma_reg_r, dma_reg_w)
 	AM_RANGE(0x40, 0x40) AM_READWRITE(syn_r, syn_w)
 	AM_RANGE(0x60, 0x60) AM_READWRITE(zfg_r, zfg_w)
-	AM_RANGE(0xFF, 0xFF) AM_RAM
+	AM_RANGE(0xff, 0xff) AM_RAM
 ADDRESS_MAP_END
 
 MACHINE_CONFIG_FRAGMENT( m1comm )
@@ -173,7 +173,7 @@ READ8_MEMBER(m1comm_device::dlc_reg_r)
 	if (!m_cn)
 	{
 		device_reset();
-		return 0xFF;
+		return 0xff;
 	}
 	// dirty hack to keep Z80 in RESET state
 
@@ -211,7 +211,7 @@ WRITE8_MEMBER(m1comm_device::dma_reg_w)
 
 READ8_MEMBER(m1comm_device::syn_r)
 {
-	uint8_t result = m_syn | 0xFC;
+	uint8_t result = m_syn | 0xfc;
 #ifdef __M1COMM_VERBOSE__
 	osd_printf_verbose("m1comm-syn_r: read register %02x for value %02x\n", offset, result);
 #endif
diff --git a/src/mame/machine/m1comm.h b/src/mame/machine/m1comm.h
index c9adb75..2321c5e 100644
--- a/src/mame/machine/m1comm.h
+++ b/src/mame/machine/m1comm.h
@@ -69,13 +69,13 @@ private:
 	uint8_t m_shared[0x1000]; // 2x 2k = 4k; model1 accesses this with 16bit data and 11bit address (A0 to A10)
 	uint8_t m_dlc_reg[0x20];  // MB89374 registers
 	uint8_t m_dma_reg[0x20];  // MB89237A registers
-	uint8_t   m_syn;                      // bit0 is stored; purpose unknown, bit1 is used to enable/disable VINT/IRQ5
-	uint8_t   m_zfg;                      // z80 flip gate? purpose unknown, bit0 is stored
-	uint8_t   m_cn;                           // bit0 is used to enable/disable the comm board
-	uint8_t   m_fg;                           // flip gate? purpose unknown, bit0 is stored, bit7 is connected to ZFG bit 0
+	uint8_t m_syn;            // bit0 is stored; purpose unknown, bit1 is used to enable/disable VINT/IRQ5
+	uint8_t m_zfg;            // z80 flip gate? purpose unknown, bit0 is stored
+	uint8_t m_cn;             // bit0 is used to enable/disable the comm board
+	uint8_t m_fg;             // flip gate? purpose unknown, bit0 is stored, bit7 is connected to ZFG bit 0
 
-	emu_file m_line_rx;    // rx line - can be either differential, simple serial or toslink
-	emu_file m_line_tx;    // tx line - is differential, simple serial and toslink
+	emu_file m_line_rx;       // rx line - can be either differential, simple serial or toslink
+	emu_file m_line_tx;       // tx line - is differential, simple serial and toslink
 	char m_localhost[256];
 	char m_remotehost[256];
 	uint8_t m_buffer[0x1000];
diff --git a/src/mame/machine/m2comm.cpp b/src/mame/machine/m2comm.cpp
index f3355b0..8d15c93 100644
--- a/src/mame/machine/m2comm.cpp
+++ b/src/mame/machine/m2comm.cpp
@@ -238,7 +238,7 @@ void m2comm_device::device_reset()
 
 READ8_MEMBER(m2comm_device::zfg_r)
 {
-	uint8_t result = m_zfg | 0xFE;
+	uint8_t result = m_zfg | (~m_fg << 7) | 0x7e;
 #ifdef __M2COMM_VERBOSE__
 	osd_printf_verbose("m2comm-zfg_r: read register %02x for value %02x\n", offset, result);
 #endif
@@ -272,7 +272,7 @@ WRITE8_MEMBER(m2comm_device::share_w)
 
 READ8_MEMBER(m2comm_device::cn_r)
 {
-	return m_cn;
+	return m_cn | 0xfe;
 }
 
 WRITE8_MEMBER(m2comm_device::cn_w)
@@ -288,6 +288,9 @@ WRITE8_MEMBER(m2comm_device::cn_w)
 		// reset command
 		osd_printf_verbose("M2COMM: board disabled\n");
 		m_linkenable = 0x00;
+		m_zfg = 0;
+		m_cn = 0;
+		m_fg = 0;
 	}
 	else
 	{
@@ -297,9 +300,25 @@ WRITE8_MEMBER(m2comm_device::cn_w)
 		m_linkid = 0x00;
 		m_linkalive = 0x00;
 		m_linkcount = 0x00;
-		m_linktimer = 0x00E8; // 58 fps * 4s
+		m_linktimer = 0x00e8; // 58 fps * 4s
+
+		// zero memory
+		for (int i = 0; i < 0x4000; i++)
+		{
+			m_shared[i] = 0x00;
+		}
+
+		// TODO - check EPR-16726 on Daytona USA and Sega Rally Championship
+		// EPR-18643(A) - these are accessed by VirtuaON and Sega Touring Car Championship
+
+		// frameSize - 0x0e00
+		m_shared[0x12] = 0x00;
+		m_shared[0x13] = 0x0e;
+
+		// frameOffset - 0x01c0
+		m_shared[0x14] = 0xc0;
+		m_shared[0x15] = 0x01;
 
-		comm_init();
 		comm_tick();
 	}
 #endif
@@ -307,7 +326,7 @@ WRITE8_MEMBER(m2comm_device::cn_w)
 
 READ8_MEMBER(m2comm_device::fg_r)
 {
-	return m_fg | (~m_zfg << 7);
+	return m_fg | (~m_zfg << 7) | 0x7e;
 }
 
 WRITE8_MEMBER(m2comm_device::fg_w)
@@ -324,20 +343,6 @@ void m2comm_device::check_vint_irq()
 }
 
 #ifdef __M2COMM_SIMULATION__
-void m2comm_device::comm_init()
-{
-	// TODO - check EPR-16726 on Daytona USA and Sega Rally Championship
-	// EPR-18643(A) - these are accessed by VirtuaON and Sega Touring Car Championship
-
-	// frameSize - 0xe00
-	m_shared[0x12] = 0x00;
-	m_shared[0x13] = 0x0e;
-
-	// frameOffset - 0x1c0
-	m_shared[0x14] = 0xc0;
-	m_shared[0x15] = 0x01;
-}
-
 void m2comm_device::comm_tick()
 {
 	if (m_linkenable == 0x01)
@@ -465,6 +470,7 @@ void m2comm_device::comm_tick()
 						m_buffer[1] = 0x01;
 						m_buffer[2] = 0x00;
 						m_line_tx.write(m_buffer, dataSize);
+						m_linktimer = 0x00e8; // 58 fps * 4s
 					}
 
 					// send second packet
diff --git a/src/mame/machine/m2comm.h b/src/mame/machine/m2comm.h
index c525a38..0b9cc97 100644
--- a/src/mame/machine/m2comm.h
+++ b/src/mame/machine/m2comm.h
@@ -28,7 +28,7 @@ public:
 	// single bit registers (74LS74)
 	DECLARE_READ8_MEMBER(zfg_r);
 	DECLARE_WRITE8_MEMBER(zfg_w);
-	// shared memory 2k
+	// shared memory 16k (these are actually 2x 16k bank switched)
 	DECLARE_READ8_MEMBER(share_r);
 	DECLARE_WRITE8_MEMBER(share_w);
 
@@ -47,9 +47,6 @@ public:
 
 	// IRQ logic - 5 = VINT, 7 = DLC
 	void check_vint_irq();
-#ifdef __M2COMM_SIMULATION__
-	void set_linktype(uint16_t linktype);
-#endif
 
 protected:
 	// device-level overrides
@@ -58,12 +55,12 @@ protected:
 
 private:
 	uint8_t m_shared[0x4000]; // 16k shared memory
-	uint8_t   m_zfg;                      // z80 flip gate? purpose unknown, bit0 is stored
-	uint8_t   m_cn;                           // bit0 is used to enable/disable the comm board
-	uint8_t   m_fg;                           // flip gate? purpose unknown, bit0 is stored, bit7 is connected to ZFG bit 0
+	uint8_t m_zfg;            // z80 flip gate - bit 0 switches memory banks, bit7 is connected to FG bit 0
+	uint8_t m_cn;             // bit0 is used to enable/disable the comm board
+	uint8_t m_fg;             // i960 flip gate - bit0 is stored, bit7 is connected to ZFG bit 0
 
-	emu_file m_line_rx;    // rx line - can be either differential, simple serial or toslink
-	emu_file m_line_tx;    // tx line - is differential, simple serial and toslink
+	emu_file m_line_rx;       // rx line - can be either differential, simple serial or toslink
+	emu_file m_line_tx;       // tx line - is differential, simple serial and toslink
 	char m_localhost[256];
 	char m_remotehost[256];
 	uint8_t m_buffer[0x4000];
@@ -75,9 +72,6 @@ private:
 	uint8_t m_linkid;
 	uint8_t m_linkcount;
 
-	uint16_t m_linktype;
-
-	void comm_init();
 	void comm_tick();
 #endif
 };
diff --git a/src/mame/machine/mcr68.cpp b/src/mame/machine/mcr68.cpp
index 4866a30..ae00aa8 100644
--- a/src/mame/machine/mcr68.cpp
+++ b/src/mame/machine/mcr68.cpp
@@ -11,32 +11,6 @@
 #include "includes/mcr68.h"
 
 #define VERBOSE 0
-#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
-
-/*************************************
- *
- *  6821 PIA declarations
- *
- *************************************/
-
-READ8_MEMBER(mcr68_state::zwackery_port_1_r)
-{
-	uint8_t ret = ioport("IN1")->read();
-
-	downcast<pia6821_device *>(machine().device("pia1"))->set_port_a_z_mask(ret);
-
-	return ret;
-}
-
-
-READ8_MEMBER(mcr68_state::zwackery_port_3_r)
-{
-	uint8_t ret = ioport("IN3")->read();
-
-	downcast<pia6821_device *>(machine().device("pia2"))->set_port_a_z_mask(ret);
-
-	return ret;
-}
 
 
 
@@ -48,104 +22,43 @@ READ8_MEMBER(mcr68_state::zwackery_port_3_r)
 
 MACHINE_START_MEMBER(mcr68_state,mcr68)
 {
-	for (int i = 0; i < 3; i++)
-	{
-		struct counter_state *m6840 = &m_m6840_state[i];
-
-		m6840->timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mcr68_state::counter_fired_callback),this));
-
-		save_item(m6840->control, "m6840/control", i);
-		save_item(m6840->latch, "m6840/latch", i);
-		save_item(m6840->count, "m6840/count", i);
-		save_item(m6840->timer_active, "m6840/timer_active", i);
-	}
-
-	save_item(NAME(m_m6840_status));
-	save_item(NAME(m_m6840_status_read_since_int));
-	save_item(NAME(m_m6840_msb_buffer));
-	save_item(NAME(m_m6840_lsb_buffer));
-	save_item(NAME(m_m6840_irq_state));
-	save_item(NAME(m_v493_irq_state));
-	save_item(NAME(m_zwackery_sound_data));
-}
-
-
-void mcr68_state::mcr68_common_init()
-{
-	/* reset the 6840's */
-	m_m6840_counter_periods[0] = attotime::from_hz(30);         /* clocked by /VBLANK */
-	m_m6840_counter_periods[1] = attotime::never;               /* grounded */
-	m_m6840_counter_periods[2] = attotime::from_hz(512 * 30);   /* clocked by /HSYNC */
-
-	m_m6840_status = 0x00;
-	m_m6840_status_read_since_int = 0x00;
-	m_m6840_msb_buffer = m_m6840_lsb_buffer = 0;
-	for (int i = 0; i < 3; i++)
-	{
-		struct counter_state *m6840 = &m_m6840_state[i];
-
-		m6840->control = 0x00;
-		m6840->latch = 0xffff;
-		m6840->count = 0xffff;
-		m6840->timer->enable(false);
-		m6840->timer_active = 0;
-		m6840->period = m_m6840_counter_periods[i];
-	}
-
-	/* initialize the clock */
-	m_m6840_internal_counter_period = attotime::from_hz(m_maincpu->unscaled_clock() / 10);
 }
 
 
 MACHINE_RESET_MEMBER(mcr68_state,mcr68)
 {
 	/* for the most part all MCR/68k games are the same */
-	mcr68_common_init();
 	m_v493_callback = timer_expired_delegate(FUNC(mcr68_state::mcr68_493_callback),this);
-
-	/* vectors are 1 and 2 */
-	m_v493_irq_vector = 1;
-	m_m6840_irq_vector = 2;
-}
-
-
-MACHINE_START_MEMBER(mcr68_state,zwackery)
-{
-	MACHINE_START_CALL_MEMBER(mcr68);
-}
-
-
-MACHINE_RESET_MEMBER(mcr68_state,zwackery)
-{
-	/* for the most part all MCR/68k games are the same */
-	mcr68_common_init();
-	m_v493_callback = timer_expired_delegate(FUNC(mcr68_state::zwackery_493_callback),this);
-
-	/* vectors are 5 and 6 */
-	m_v493_irq_vector = 5;
-	m_m6840_irq_vector = 6;
 }
 
 
 
 /*************************************
  *
- *  Generic MCR interrupt handler
+ *  Scanline callback
  *
  *************************************/
 
-INTERRUPT_GEN_MEMBER(mcr68_state::mcr68_interrupt)
+TIMER_DEVICE_CALLBACK_MEMBER( mcr68_state::scanline_cb )
 {
-	/* update the 6840 VBLANK clock */
-	if (!m_m6840_state[0].timer_active)
-		subtract_from_counter(0, 1);
+	// VSYNC
+	if (param == 0)
+	{
+		if (VERBOSE)
+			logerror("--- VBLANK ---\n");
+
+		m_ptm->set_c1(0);
+		m_ptm->set_c1(1);
 
-	logerror("--- VBLANK ---\n");
+		/* also set a timer to generate the 493 signal at a specific time before the next VBLANK */
+		/* the timing of this is crucial for Blasted and Tri-Sports, which check the timing of */
+		/* VBLANK and 493 using counter 2 */
+		machine().scheduler().timer_set(attotime::from_hz(30) - m_timing_factor, m_v493_callback);
+	}
 
-	/* also set a timer to generate the 493 signal at a specific time before the next VBLANK */
-	/* the timing of this is crucial for Blasted and Tri-Sports, which check the timing of */
-	/* VBLANK and 493 using counter 2 */
-	machine().scheduler().timer_set(attotime::from_hz(30) - m_timing_factor, m_v493_callback);
+	// HSYNC
+	m_ptm->set_c3(0);
+	m_ptm->set_c3(1);
 }
 
 
@@ -156,386 +69,17 @@ INTERRUPT_GEN_MEMBER(mcr68_state::mcr68_interrupt)
  *
  *************************************/
 
-void mcr68_state::update_mcr68_interrupts()
-{
-	m_maincpu->set_input_line(m_v493_irq_vector, m_v493_irq_state ? ASSERT_LINE : CLEAR_LINE);
-	m_maincpu->set_input_line(m_m6840_irq_vector, m_m6840_irq_state ? ASSERT_LINE : CLEAR_LINE);
-}
-
-
 TIMER_CALLBACK_MEMBER(mcr68_state::mcr68_493_off_callback)
 {
-	m_v493_irq_state = 0;
-	update_mcr68_interrupts();
+	m_maincpu->set_input_line(1, CLEAR_LINE);
 }
 
 
 TIMER_CALLBACK_MEMBER(mcr68_state::mcr68_493_callback)
 {
-	m_v493_irq_state = 1;
-	update_mcr68_interrupts();
+	m_maincpu->set_input_line(1, ASSERT_LINE);
 	machine().scheduler().timer_set(m_screen->scan_period(), timer_expired_delegate(FUNC(mcr68_state::mcr68_493_off_callback),this));
-	logerror("--- (INT1) ---\n");
-}
-
-
-
-/*************************************
- *
- *  Zwackery-specific interfaces
- *
- *************************************/
-
-WRITE8_MEMBER(mcr68_state::zwackery_pia0_w)
-{
-	/* bit 7 is the watchdog */
-	if (!(data & 0x80)) m_watchdog->watchdog_reset();
-
-	/* bits 5 and 6 control hflip/vflip */
-	/* bits 3 and 4 control coin counters? */
-	/* bits 0, 1 and 2 control meters? */
-}
-
-
-WRITE8_MEMBER(mcr68_state::zwackery_pia1_w)
-{
-	m_zwackery_sound_data = (data >> 4) & 0x0f;
-}
-
-
-WRITE_LINE_MEMBER(mcr68_state::zwackery_ca2_w)
-{
-	address_space &space = m_maincpu->space(AS_PROGRAM);
-	m_chip_squeak_deluxe->write(space, 0, (state << 4) | m_zwackery_sound_data);
-}
-
-
-WRITE_LINE_MEMBER(mcr68_state::zwackery_pia_irq)
-{
-	pia6821_device *pia = machine().device<pia6821_device>("pia0");
-	m_v493_irq_state = pia->irq_a_state() | pia->irq_b_state();
-	update_mcr68_interrupts();
-}
-
-
-TIMER_CALLBACK_MEMBER(mcr68_state::zwackery_493_off_callback)
-{
-	pia6821_device *pia = machine().device<pia6821_device>("pia0");
-	pia->ca1_w(0);
-}
-
-
-TIMER_CALLBACK_MEMBER(mcr68_state::zwackery_493_callback)
-{
-	pia6821_device *pia = machine().device<pia6821_device>("pia0");
-
-	pia->ca1_w(1);
-	machine().scheduler().timer_set(m_screen->scan_period(), timer_expired_delegate(FUNC(mcr68_state::zwackery_493_off_callback),this));
-}
-
-
-
-/*************************************
- *
- *  M6840 timer utilities
- *
- *************************************/
-
-inline void mcr68_state::update_interrupts()
-{
-	m_m6840_status &= ~0x80;
-
-	if ((m_m6840_status & 0x01) && (m_m6840_state[0].control & 0x40)) m_m6840_status |= 0x80;
-	if ((m_m6840_status & 0x02) && (m_m6840_state[1].control & 0x40)) m_m6840_status |= 0x80;
-	if ((m_m6840_status & 0x04) && (m_m6840_state[2].control & 0x40)) m_m6840_status |= 0x80;
-
-	m_m6840_irq_state = m_m6840_status >> 7;
-	update_mcr68_interrupts();
-}
-
-
-void mcr68_state::subtract_from_counter(int counter, int count)
-{
-	struct counter_state *m6840 = &m_m6840_state[counter];
-
-	/* dual-byte mode */
-	if (m6840->control & 0x04)
-	{
-		int lsb = m6840->count & 0xff;
-		int msb = m6840->count >> 8;
-
-		/* count the clocks */
-		lsb -= count;
-
-		/* loop while we're less than zero */
-		while (lsb < 0)
-		{
-			/* borrow from the MSB */
-			lsb += (m6840->latch & 0xff) + 1;
-			msb--;
-
-			/* if MSB goes less than zero, we've expired */
-			if (msb < 0)
-			{
-				m_m6840_status |= 1 << counter;
-				m_m6840_status_read_since_int &= ~(1 << counter);
-				update_interrupts();
-				msb = (m6840->latch >> 8) + 1;
-				LOG(("** Counter %d fired\n", counter));
-			}
-		}
 
-		/* store the result */
-		m6840->count = (msb << 8) | lsb;
-	}
-
-	/* word mode */
-	else
-	{
-		int word = m6840->count;
-
-		/* count the clocks */
-		word -= count;
-
-		/* loop while we're less than zero */
-		while (word < 0)
-		{
-			/* borrow from the MSB */
-			word += m6840->latch + 1;
-
-			/* we've expired */
-			m_m6840_status |= 1 << counter;
-			m_m6840_status_read_since_int &= ~(1 << counter);
-			update_interrupts();
-			LOG(("** Counter %d fired\n", counter));
-		}
-
-		/* store the result */
-		m6840->count = word;
-	}
-}
-
-
-TIMER_CALLBACK_MEMBER(mcr68_state::counter_fired_callback)
-{
-	int count = param >> 2;
-	int counter = param & 3;
-	struct counter_state *m6840 = &m_m6840_state[counter];
-
-	/* reset the timer */
-	m6840->timer_active = 0;
-
-	/* subtract it all from the counter; this will generate an interrupt */
-	subtract_from_counter(counter, count);
-}
-
-
-void mcr68_state::reload_count(int counter)
-{
-	struct counter_state *m6840 = &m_m6840_state[counter];
-	attotime period;
-	attotime total_period;
-	int count;
-
-	/* copy the latched value in */
-	m6840->count = m6840->latch;
-
-	/* counter 0 is self-updating if clocked externally */
-	if (counter == 0 && !(m6840->control & 0x02))
-	{
-		m6840->timer->adjust(attotime::never);
-		m6840->timer_active = 0;
-		return;
-	}
-
-	/* determine the clock period for this timer */
-	if (m6840->control & 0x02)
-		period = m_m6840_internal_counter_period;
-	else
-		period = m_m6840_counter_periods[counter];
-
-	/* determine the number of clock periods before we expire */
-	count = m6840->count;
-	if (m6840->control & 0x04)
-		count = ((count >> 8) + 1) * ((count & 0xff) + 1);
-	else
-		count = count + 1;
-
-	/* set the timer */
-	total_period = period * count;
-LOG(("reload_count(%d): period = %f  count = %d\n", counter, period.as_double(), count));
-	m6840->timer->adjust(total_period, (count << 2) + counter);
-	m6840->timer_active = 1;
-}
-
-
-uint16_t mcr68_state::compute_counter(int counter)
-{
-	struct counter_state *m6840 = &m_m6840_state[counter];
-	attotime period;
-	int remaining;
-
-	/* if there's no timer, return the count */
-	if (!m6840->timer_active)
-		return m6840->count;
-
-	/* determine the clock period for this timer */
-	if (m6840->control & 0x02)
-		period = m_m6840_internal_counter_period;
-	else
-		period = m_m6840_counter_periods[counter];
-	/* see how many are left */
-	remaining = m6840->timer->remaining().as_attoseconds() / period.as_attoseconds();
-
-	/* adjust the count for dual byte mode */
-	if (m6840->control & 0x04)
-	{
-		int divisor = (m6840->count & 0xff) + 1;
-		int msb = remaining / divisor;
-		int lsb = remaining % divisor;
-		remaining = (msb << 8) | lsb;
-	}
-
-	return remaining;
-}
-
-
-
-/*************************************
- *
- *  M6840 timer I/O
- *
- *************************************/
-
-WRITE8_MEMBER(mcr68_state::mcr68_6840_w_common)
-{
-	int i;
-
-	/* offsets 0 and 1 are control registers */
-	if (offset < 2)
-	{
-		int counter = (offset == 1) ? 1 : (m_m6840_state[1].control & 0x01) ? 0 : 2;
-		struct counter_state *m6840 = &m_m6840_state[counter];
-		uint8_t diffs = data ^ m6840->control;
-
-		m6840->control = data;
-
-		/* reset? */
-		if (counter == 0 && (diffs & 0x01))
-		{
-			/* holding reset down */
-			if (data & 0x01)
-			{
-				for (i = 0; i < 3; i++)
-				{
-					m_m6840_state[i].timer->adjust(attotime::never);
-					m_m6840_state[i].timer_active = 0;
-				}
-			}
-
-			/* releasing reset */
-			else
-			{
-				for (i = 0; i < 3; i++)
-					reload_count(i);
-			}
-
-			m_m6840_status = 0;
-			update_interrupts();
-		}
-
-		/* changing the clock source? (needed for Zwackery) */
-		if (diffs & 0x02)
-			reload_count(counter);
-
-		LOG(("%06X:Counter %d control = %02X\n", space.device().safe_pcbase(), counter, data));
-	}
-
-	/* offsets 2, 4, and 6 are MSB buffer registers */
-	else if ((offset & 1) == 0)
-	{
-		LOG(("%06X:MSB = %02X\n", space.device().safe_pcbase(), data));
-		m_m6840_msb_buffer = data;
-	}
-
-	/* offsets 3, 5, and 7 are Write Timer Latch commands */
-	else
-	{
-		int counter = (offset - 2) / 2;
-		struct counter_state *m6840 = &m_m6840_state[counter];
-		m6840->latch = (m_m6840_msb_buffer << 8) | (data & 0xff);
-
-		/* clear the interrupt */
-		m_m6840_status &= ~(1 << counter);
-		update_interrupts();
-
-		/* reload the count if in an appropriate mode */
-		if (!(m6840->control & 0x10))
-			reload_count(counter);
-
-		LOG(("%06X:Counter %d latch = %04X\n", space.device().safe_pcbase(), counter, m6840->latch));
-	}
-}
-
-
-READ16_MEMBER(mcr68_state::mcr68_6840_r_common)
-{
-	/* offset 0 is a no-op */
-	if (offset == 0)
-		return 0;
-
-	/* offset 1 is the status register */
-	else if (offset == 1)
-	{
-		LOG(("%06X:Status read = %04X\n", space.device().safe_pcbase(), m_m6840_status));
-		m_m6840_status_read_since_int |= m_m6840_status & 0x07;
-		return m_m6840_status;
-	}
-
-	/* offsets 2, 4, and 6 are Read Timer Counter commands */
-	else if ((offset & 1) == 0)
-	{
-		int counter = (offset - 2) / 2;
-		int result = compute_counter(counter);
-
-		/* clear the interrupt if the status has been read */
-		if (m_m6840_status_read_since_int & (1 << counter))
-			m_m6840_status &= ~(1 << counter);
-		update_interrupts();
-
-		m_m6840_lsb_buffer = result & 0xff;
-
-		LOG(("%06X:Counter %d read = %04X\n", space.device().safe_pcbase(), counter, result));
-		return result >> 8;
-	}
-
-	/* offsets 3, 5, and 7 are LSB buffer registers */
-	else
-		return m_m6840_lsb_buffer;
-}
-
-
-WRITE16_MEMBER(mcr68_state::mcr68_6840_upper_w)
-{
-	if (ACCESSING_BITS_8_15)
-		mcr68_6840_w_common(space, offset, (data >> 8) & 0xff);
-}
-
-
-WRITE16_MEMBER(mcr68_state::mcr68_6840_lower_w)
-{
-	if (ACCESSING_BITS_0_7)
-		mcr68_6840_w_common(space, offset, data & 0xff);
-}
-
-
-READ16_MEMBER(mcr68_state::mcr68_6840_upper_r)
-{
-	return (mcr68_6840_r_common(space,offset,0) << 8) | 0x00ff;
-}
-
-
-READ16_MEMBER(mcr68_state::mcr68_6840_lower_r)
-{
-	return mcr68_6840_r_common(space,offset,0) | 0xff00;
+	if (VERBOSE)
+		logerror("--- (INT1) ---\n");
 }
diff --git a/src/mame/machine/midwayic.cpp b/src/mame/machine/midwayic.cpp
index 52247aa..583434e 100644
--- a/src/mame/machine/midwayic.cpp
+++ b/src/mame/machine/midwayic.cpp
@@ -91,7 +91,7 @@ void midway_serial_pic_device::generate_serial_data(int upper)
 /*************************************
  *
  *  Original serial number PIC
- *  interface
+ *  interface - simulation
  *
  *************************************/
 
@@ -113,7 +113,7 @@ const device_type MIDWAY_SERIAL_PIC = &device_creator<midway_serial_pic_device>;
 //-------------------------------------------------
 
 midway_serial_pic_device::midway_serial_pic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
-	device_t(mconfig, MIDWAY_SERIAL_PIC2, "Midway Serial Pic", tag, owner, clock, "midway_serial_pic", __FILE__),
+	device_t(mconfig, MIDWAY_SERIAL_PIC2, "Midway Serial Pic Simulation", tag, owner, clock, "midway_serial_pic_sim", __FILE__),
 	m_upper(0),
 	m_buff(0),
 	m_idx(0),
@@ -192,6 +192,91 @@ WRITE8_MEMBER(midway_serial_pic_device::write)
 }
 
 
+/*************************************
+ *
+ *  Original serial number PIC
+ *  interface - emulation
+ *
+ *************************************/
+
+
+const device_type MIDWAY_SERIAL_PIC_EMU = &device_creator<midway_serial_pic_emu_device>;
+
+
+//-------------------------------------------------
+//  midway_serial_pic_emu_device - constructor
+//-------------------------------------------------
+
+midway_serial_pic_emu_device::midway_serial_pic_emu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+	device_t(mconfig, MIDWAY_SERIAL_PIC_EMU, "Midway Serial Pic Emulation", tag, owner, clock, "midway_serial_pic_emu", __FILE__)
+{
+}
+
+//-------------------------------------------------
+//  device_start - device-specific startup
+//-------------------------------------------------
+
+void midway_serial_pic_emu_device::device_start()
+{
+}
+
+
+READ_LINE_MEMBER(midway_serial_pic_emu_device::PIC16C5X_T0_clk_r)
+{
+//  printf("%s: PIC16C5X_T0_clk_r\n", machine().describe_context());
+	return 0;
+}
+
+READ8_MEMBER(midway_serial_pic_emu_device::read_a)
+{
+//  printf("%s: read_a\n", space.machine().describe_context());
+	return 0x00;
+}
+
+READ8_MEMBER(midway_serial_pic_emu_device::read_b)
+{
+//  printf("%s: read_b\n", space.machine().describe_context());
+	return 0x00;
+}
+
+READ8_MEMBER(midway_serial_pic_emu_device::read_c)
+{
+//  used
+//  printf("%s: read_c\n", space.machine().describe_context());
+	return 0x00;
+}
+
+WRITE8_MEMBER(midway_serial_pic_emu_device::write_a)
+{
+//  printf("%s: write_a %02x\n", space.machine().describe_context(), data);
+}
+
+WRITE8_MEMBER(midway_serial_pic_emu_device::write_b)
+{
+//  printf("%s: write_b %02x\n", space.machine().describe_context(), data);
+}
+
+WRITE8_MEMBER(midway_serial_pic_emu_device::write_c)
+{
+//  used
+//  printf("%s: write_c %02x\n", space.machine().describe_context(), data);
+}
+
+static MACHINE_CONFIG_FRAGMENT( midway_pic )
+	MCFG_CPU_ADD("pic", PIC16C57, 12000000)    /* ? Mhz */
+	MCFG_PIC16C5x_WRITE_A_CB(WRITE8(midway_serial_pic_emu_device, write_a))
+	MCFG_PIC16C5x_READ_B_CB(READ8(midway_serial_pic_emu_device, read_b))
+	MCFG_PIC16C5x_WRITE_B_CB(WRITE8(midway_serial_pic_emu_device, write_b))
+	MCFG_PIC16C5x_READ_C_CB(READ8(midway_serial_pic_emu_device, read_c))
+	MCFG_PIC16C5x_WRITE_C_CB(WRITE8(midway_serial_pic_emu_device, write_c))
+	MCFG_PIC16C5x_T0_CB(READLINE(midway_serial_pic_emu_device, PIC16C5X_T0_clk_r))
+MACHINE_CONFIG_END
+
+machine_config_constructor midway_serial_pic_emu_device::device_mconfig_additions() const
+{
+	return MACHINE_CONFIG_NAME( midway_pic );
+}
+
 
 /*************************************
  *
@@ -593,6 +678,7 @@ const device_type MIDWAY_IOASIC = &device_creator<midway_ioasic_device>;
 
 midway_ioasic_device::midway_ioasic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
 	midway_serial_pic2_device(mconfig, MIDWAY_IOASIC, "Midway IOASIC", tag, owner, clock, "midway_ioasic", __FILE__),
+	m_serial_tx_cb(*this),
 	m_has_dcs(0),
 	m_has_cage(0),
 	m_dcs_cpu(nullptr),
@@ -657,6 +743,7 @@ void midway_ioasic_device::device_start()
 	m_shuffle_map = &shuffle_maps[m_shuffle_type][0];
 	// resolve callbacks
 	m_irq_callback.resolve_safe();
+	m_serial_tx_cb.resolve_safe();
 
 	/* initialize the PIC */
 	midway_serial_pic2_device::device_start();
@@ -1028,6 +1115,12 @@ WRITE32_MEMBER( midway_ioasic_device::packed_w )
 		write(space, offset*2+1, data >> 16, 0x0000ffff);
 }
 
+WRITE8_MEMBER(midway_ioasic_device::serial_rx_w)
+{
+	m_reg[IOASIC_UARTIN] = data | 0x1000;
+	update_ioasic_irq();
+
+}
 
 WRITE32_MEMBER( midway_ioasic_device::write )
 {
@@ -1068,8 +1161,13 @@ WRITE32_MEMBER( midway_ioasic_device::write )
 				m_reg[IOASIC_UARTIN] = (newreg & 0x00ff) | 0x1000;
 				update_ioasic_irq();
 			}
-			else if (PRINTF_DEBUG)
-				osd_printf_debug("%c", data & 0xff);
+			else {
+				m_serial_tx_cb(data & 0xff);
+				if (PRINTF_DEBUG) {
+					osd_printf_info("%c", data & 0xff);
+					logerror("%c", data & 0xff);
+				}
+			}
 			break;
 
 		case IOASIC_SOUNDCTL:
diff --git a/src/mame/machine/midwayic.h b/src/mame/machine/midwayic.h
index 707988c..ddca0ab 100644
--- a/src/mame/machine/midwayic.h
+++ b/src/mame/machine/midwayic.h
@@ -11,8 +11,9 @@
 
 #include "audio/cage.h"
 #include "audio/dcs.h"
+#include "cpu/pic16c5x/pic16c5x.h"
 
-/* 1st generation Midway serial PIC */
+/* 1st generation Midway serial PIC - simulation*/
 
 class midway_serial_pic_device : public device_t
 {
@@ -52,6 +53,41 @@ extern const device_type MIDWAY_SERIAL_PIC;
 #define MCFG_MIDWAY_SERIAL_PIC_UPPER(_upper) \
 	midway_serial_pic_device::static_set_upper(*device, _upper);
 
+/* 1st generation Midway serial PIC - emulation */
+
+class midway_serial_pic_emu_device : public device_t
+{
+public:
+	// construction/destruction
+	midway_serial_pic_emu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+	midway_serial_pic_emu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, uint32_t clock, const char *shortname, const char *source);
+
+	DECLARE_READ_LINE_MEMBER(PIC16C5X_T0_clk_r);
+	DECLARE_READ8_MEMBER(read_a);
+	DECLARE_READ8_MEMBER(read_b);
+	DECLARE_READ8_MEMBER(read_c);
+	DECLARE_WRITE8_MEMBER(write_a);
+	DECLARE_WRITE8_MEMBER(write_b);
+	DECLARE_WRITE8_MEMBER(write_c);
+
+
+
+
+protected:
+	// device-level overrides
+	virtual machine_config_constructor device_mconfig_additions() const override;
+	virtual void device_start() override;
+
+private:
+
+};
+
+
+// device type definition
+extern const device_type MIDWAY_SERIAL_PIC_EMU;
+
+
+
 /* 2nd generation Midway serial/NVRAM/RTC PIC */
 
 // ======================> midway_serial_pic2_device
@@ -125,6 +161,7 @@ public:
 	static void static_set_shuffle_default(device_t &device, uint8_t shuffle) { downcast<midway_ioasic_device &>(device).m_shuffle_default = shuffle; }
 	static void static_set_auto_ack(device_t &device, uint8_t auto_ack) { downcast<midway_ioasic_device &>(device).m_auto_ack = auto_ack; }
 	template<class _Object> static devcb_base &set_irqhandler_callback(device_t &device, _Object object) { return downcast<midway_ioasic_device &>(device).m_irq_callback.set_callback(object); }
+	template<class _Object> static devcb_base &set_serial_tx_callback(device_t &device, _Object object) { return downcast<midway_ioasic_device &>(device).m_serial_tx_cb.set_callback(object); }
 
 	void set_shuffle_state(int state);
 	void fifo_w(uint16_t data);
@@ -145,6 +182,8 @@ public:
 
 	DECLARE_WRITE8_MEMBER(cage_irq_handler);
 
+	DECLARE_WRITE8_MEMBER(serial_rx_w);
+
 	void ioasic_reset();
 
 protected:
@@ -155,6 +194,7 @@ private:
 	void ioasic_register_state();
 	void update_ioasic_irq();
 
+	devcb_write8    m_serial_tx_cb;
 
 	uint32_t  m_reg[16];
 	uint8_t   m_has_dcs;
@@ -200,6 +240,9 @@ extern const device_type MIDWAY_IOASIC;
 #define MCFG_MIDWAY_IOASIC_AUTO_ACK(_ack) \
 	midway_ioasic_device::static_set_auto_ack(*device, _ack);
 
+#define MCFG_MIDWAY_IOASIC_OUT_TX_CB(_devcb) \
+	devcb = &midway_ioasic_device::set_serial_tx_callback(*device, DEVCB_##_devcb);
+
 
 enum
 {
diff --git a/src/mame/machine/midwunit.cpp b/src/mame/machine/midwunit.cpp
index 4ae8a44..730ca5f 100644
--- a/src/mame/machine/midwunit.cpp
+++ b/src/mame/machine/midwunit.cpp
@@ -89,7 +89,7 @@ WRITE16_MEMBER(midwunit_state::midwunit_io_w)
 			m_dcs->reset_w(newword & 0x10);
 
 			/* bit 5 (active low) reset security chip */
-			m_midway_serial_pic->reset_w(newword & 0x20);
+			if (m_midway_serial_pic) m_midway_serial_pic->reset_w(newword & 0x20);
 			break;
 
 		case 3:
@@ -127,8 +127,12 @@ READ16_MEMBER(midwunit_state::midwunit_io_r)
 			return m_ports[offset]->read();
 
 		case 4:
-			return (m_midway_serial_pic->status_r(space,0) << 12) | midwunit_sound_state_r(space,0,0xffff);
+		{
+			int picret = 0;
+			if (m_midway_serial_pic) picret = m_midway_serial_pic->status_r(space, 0);
 
+			return (picret << 12) | midwunit_sound_state_r(space, 0, 0xffff);
+		}
 		default:
 			logerror("%08X:Unknown I/O read from %d\n", space.device().safe_pc(), offset);
 			break;
@@ -357,14 +361,18 @@ MACHINE_RESET_MEMBER(midwunit_state,midwunit)
 
 READ16_MEMBER(midwunit_state::midwunit_security_r)
 {
-	return m_midway_serial_pic->read(space,0);
+	uint16_t picret = 0;
+	if (m_midway_serial_pic) picret = m_midway_serial_pic->read(space, 0);
+	return picret;
 }
 
 
 WRITE16_MEMBER(midwunit_state::midwunit_security_w)
 {
 	if (offset == 0 && ACCESSING_BITS_0_7)
-		m_midway_serial_pic->write(space, 0, data);
+	{
+		if (m_midway_serial_pic) m_midway_serial_pic->write(space, 0, data);
+	}
 }
 
 
diff --git a/src/mame/machine/naomigd.cpp b/src/mame/machine/naomigd.cpp
index 5b2e6cf..d82eb9d 100644
--- a/src/mame/machine/naomigd.cpp
+++ b/src/mame/machine/naomigd.cpp
@@ -6,7 +6,81 @@
 #include "imagedev/chd_cd.h"
 
 /*
-    Dimm board registers (add more information if you find it):
+
+  GPIO pins(main board: EEPROM, DIMM SPDs, option board: PIC16, JPs)
+   |
+  SH4 <-> 315-6154 <-> PCI bus -> Sega 315-6322 -> Host system interface (NAOMI, Triforce, Chihiro)
+   |         |                                  -> 2x DIMM RAM modules
+  RAM       RAM                -> Altera (PCI IDE Bus Master Controller) -> IDE bus -> GD-ROM or CF
+ 16MB       4MB                -> PCnet-FAST III -> Ethernet
+
+315-6154 - SH4 CPU to PCI bridge and SDRAM controller, also used in Sega Hikaru (2x)
+315-6322 - DIMM SDRAM controller, DES decryption, host system communication
+
+ SH4 address space
+-------------------
+00000000 - 001FFFFF Flash ROM (1st half - stock firmware, 2nd half - updated firmware)
+04000000 - 040000FF memory/PCI bridge registers (Sega 315-6154)
+0C000000 - 0CFFFFFF SH4 local RAM
+10000000 - 103FFFFF memory/PCI controller RAM
+14000000 - 1BFFFFFF 8x banked pages
+
+internal / PCI memory space
+-------------------
+00000000 - 000000FF DIMM controller registers (Sega 315-6322)
+10000000 - 4FFFFFFF DIMM memory, upto 1GB (if register 28 bit 1 is 0, otherwise some unknown MMIO)
+70000000 - 70FFFFFF SH4 local RAM
+78000000 - 783FFFFF 315-6154 PCI bridge RAM
+C00001xx   IDE registers                 \
+C00003xx   IDE registers                  | software configured in VxWorks, preconfigured or hardcoded in 1.02
+C000CCxx   IDE Bus Master DMA registers  /
+C1xxxxxx   Network registers
+
+PCI configuration space (enabled using memctl 1C reg)
+-------------------
+00000000 - 00000FFF unknown, write 142 to reg 04 at very start
+00001000 - 00001FFF PCI IDE controller (upper board Altera Flex) Vendor 11db Device 189d
+00002000 - 00002FFF AMD AM79C973BVC PCnet-FAST III Network
+
+DIMM controller registers
+-------------------
+14 5F703C |
+18 5F7040 |
+1C 5F7044 | 16bit  4x Communication registers
+20 5F7048 |
+24 5F704C   16bit  Interrupt register
+                   -------c ---b---a
+                    a - IRQ to DIMM (SH4 IRL3): 0 set / 1 clear
+                    b - unk, mask of a ???
+                    c - IRQ to NAOMI (HOLLY EXT 3): 0 set / 1 clear (write 0 from NAOMI seems ignored)
+
+28          16bit  dddd---c ------ba
+                    a - 0->1 NAOMI reset
+                    b - 1 seems disable DIMM RAM access, followed by write 01010101 to bank 10 offset 000110 or 000190 (some MMIO?)
+                    c - unk, set to 1 in VxWorks, 0 in 1.02
+                    d - unk, checked for == 1 in 1.02
+
+2A           8bit  possible DES decryption area size 8 MSB bits (16MB units number)
+                   VxWorks firmwares set this to ((DIMMsize >> 24) - 1), 1.02 set it to FF
+
+2C          32bit  SDRAM config
+30          32bit  DES key low
+34          32bit  DES key high
+
+SH4 IO port A bits
+-------------------
+9 select input, 0 - main/lower board, 1 - option/upper board (IDE, Net, PIC)
+     0             1
+0 DIMM SPD clk   JP? 0 - enable IDE
+1 DIMM SPD data  JP? 0 - enable Network
+2 93C46 DI       PIC16 D0
+3 93C46 CS       PIC16 D1
+4 93C46 CLK      PIC16 D2
+5 93C46 DO       PIC16 CLK
+
+
+
+    Dimm board communication registers software level usage:
 
     Name:                   Naomi   Dimm Bd.
     NAOMI_DIMM_COMMAND    = 5f703c  14000014 (16 bit):
@@ -565,6 +639,10 @@ ROM_START( dimm )
 	// unused and/or unknown security PICs
 	// 253-5508-0352E 317-0352-EXP BFC.BIN unknown, presumable some mahjong game (MJ1 ?)
 	ROM_LOAD("317-0352-exp.pic", 0x00, 0x4000, CRC(b216fbfc) SHA1(da2341003b35d1600d63fbe34d13ff3b42bdc939) )
+	// 253-5508-0364  317-0364-COM BGK.BIN unknown, have been seen with DIMM board labeled "DIMM BD NAO DGS SATL"
+	ROM_LOAD("317-0364-com.pic", 0x00, 0x4000, CRC(82975008) SHA1(6732842d4af630d6c6d96bb11ba98caed1cb6b24) )
+	// 253-5508-0422J 317-0422-JPN BHE.BIN Quest of D undumped version
+	ROM_LOAD("317-0422-jpn.pic", 0x00, 0x4000, CRC(54197fbf) SHA1(a18b5b7aec0498c7a62cacf9f2298ddefb7482c9) )
 	// 253-5508-0456J 317-0456-JPN BEG.BIN WCCF 2005-2006 undumped Japan version
 	ROM_LOAD("317-0456-jpn.pic", 0x00, 0x4000, CRC(cf3bd834) SHA1(6236cdb780260d34c02806478a39c9f3432a45e8) )
 	// 253-5508-0506J 317-0506-JPN BPK.BIN unknown, something Chihiro ?
diff --git a/src/mame/machine/nl_hazelvid.cpp b/src/mame/machine/nl_hazelvid.cpp
new file mode 100644
index 0000000..e6c3a11
--- /dev/null
+++ b/src/mame/machine/nl_hazelvid.cpp
@@ -0,0 +1,241 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+
+/***************************************************************************
+
+  Netlist (hazelvid) included from hazeltin.cpp
+
+***************************************************************************/
+
+#include "netlist/devices/net_lib.h"
+
+#ifndef __PLIB_PREPROCESSOR__
+#endif
+
+NETLIST_START(hazelvid)
+
+	SOLVER(Solver, 48000)
+	PARAM(Solver.PARALLEL, 0) // Don't do parallel solvers
+	PARAM(Solver.ACCURACY, 1e-4) // works and is sufficient
+	PARAM(NETLIST.USE_DEACTIVATE, 1)
+
+	ANALOG_INPUT(V5, 5)
+
+	TTL_INPUT(high, 1)
+	TTL_INPUT(low, 0)
+
+	MAINCLOCK(video_clk, 16632000.0)
+
+	/* Character line counter, divide-by-9 */
+	TTL_74161(u88, high, high, high, low, high, u87_6.Q, video_clk, high, high)
+
+	TTL_7404_INVERT(u87_6, u88.RCO)
+
+	TTL_74175(u81, video_clk, u88.RCO, u81.Q1, low, u88.QC, high)
+
+	TTL_7404_INVERT(u87_5, u81.Q1)
+	ALIAS(ndot, u87_5.Q)
+	TTL_7404_INVERT(u59_4, u81.Q1Q)
+	ALIAS(dot, u59_4.Q)
+
+	/* Character bucket counter */
+
+	/* least significant 4 bits */
+	TTL_74161(u70, low, low, low, low, high, u59_5.Q, u81.Q2Q, high, high)
+
+	/* most significant 4 bits */
+	TTL_74161(u69, low, low, low, low, high, u59_5.Q, u81.Q2Q, u70.RCO, u70.RCO)
+	/* Horizontal/Vertical timing signals */
+
+	/* signal lookup PROM */
+	PROM_82S126(u71, low, low, u70.QA, u70.QB, u70.QC, u70.QD, u69.QA, u69.QB, u69.QC, low)
+
+	/* signal decoding */
+	TTL_9334(u72, high, u81.Q1Q, u71.O4, u71.O1, u71.O2, u71.O3)
+	ALIAS(hms, u72.Q1)
+	ALIAS(hmsd, u72.Q2)
+	ALIAS(hblank, u72.Q3)
+	ALIAS(vstrobe, u72.Q4)
+	ALIAS(hdriveq, u72.Q5)
+	ALIAS(vidbus, u72.Q6)
+	TTL_7404_INVERT(u59_5, u72.Q7)
+
+	TTL_7400_NAND(u83_1, high, vstrobe)
+	ALIAS(char_line_clk, u83_1.Q)
+
+	/* Character line counter */
+	TTL_74161(u84, low, low, low, low, high, u83_3.Q, char_line_clk, high, high)
+	ALIAS(lc20, u84.QA)
+	ALIAS(lc21, u84.QB)
+	ALIAS(lc22, u84.QC)
+	ALIAS(lc23, u84.QD)
+	TTL_7400_NAND(u83_3, u84.QB, u84.QD)
+	TTL_7404_INVERT(u92_5, u90.QD)
+
+	TTL_7410_NAND(u89_3, u90.QD, u90.QC, u90.QA)
+
+	/* Character row counter */
+	TTL_74161(u90, low, low, low, low, high, u89_3.Q, u92_3.Q, high, high)
+	TTL_7404_INVERT(u92_3, u84.QD)
+	TTL_7404_INVERT(u92_1, u90.QB)
+
+	TTL_7474(u95_2, u92_5.Q, u95_2.QQ, high, high)
+
+	TTL_7411_AND(u91_3, u84.QA, u84.QD, u90.QB)
+	TTL_7411_AND(u91_1, u92_1.Q, u90.QA, u84.QC)
+
+	TTL_7404_INVERT(u92_2, u90.QC)
+	TTL_7411_AND(u91_2, u95_2.QQ, u92_2.Q, u92_5.Q)
+	TTL_7404_INVERT(u92_6, u91_2.Q)
+
+	/* Vertical blanking and drive */
+	TTL_7473(u85_vdrive, char_line_clk, u91_1.Q, u91_3.Q, u85_vblankq.QQ)
+	TTL_7473(u85_vblankq, char_line_clk, u92_6.Q, u91_2.Q, high)
+
+	/* Outgoing signals */
+	TTL_7404_INVERT(u73_4, hdriveq)
+	ALIAS(hdrive, u73_4.Q)
+
+	TTL_7404_INVERT(u61_6, hmsd)
+	TTL_7402_NOR(u60_1, u61_6.Q, u81.Q4)
+	ALIAS(lbc, u60_1.Q)
+
+	TTL_7404_INVERT(u74_1, u84.QB)
+	TTL_7410_NAND(u89_2, vidbus, vidbus, u82_2.Q)
+	ALIAS(ncntbenq, u89_2.Q)
+
+	TTL_7410_NAND(u89_1, u81.Q2, hmsd, u82_2.Q)
+	TTL_7400_NAND(u83_4, u89_1.Q, high)
+	ALIAS(cntclk, u83_4.Q)
+
+	TTL_7402_NOR(u60_2, hblank, u85_vblankq.QQ)
+	ALIAS(clr_vid_sr, u60_2.Q)
+
+	TTL_7404_INVERT(u92_4, u84.QB)
+	TTL_74260_NOR(u82_2, u85_vblankq.QQ, u92_3.Q, u84.QC, u92_4.Q, u84.QA)
+	TTL_7400_NAND(u83_2, vstrobe, u82_2.Q)
+	ALIAS(sync_bus_disable_q, u83_2.Q)
+
+	ALIAS(vdrive, u85_vdrive.Q)
+	TTL_7404_INVERT(u73_5, vdrive)
+	ALIAS(vdriveq, u73_5.Q)
+
+	TTL_7474(u95_1, u84.QD, u85_vblankq.QQ, high, high)
+	ALIAS(vblank, u95_1.Q)
+
+	TTL_74260_NOR(u82_1, u85_vblankq.QQ, u92_4.Q, u84.QD, u84.QC, low)
+	TTL_7404_INVERT(u61_3, u82_1.Q)
+	ALIAS(tvinterq, u61_3.Q)
+
+	TTL_INPUT(cpu_iowq, 1)
+	TTL_INPUT(cpu_ba4, 1)
+	TTL_7432_OR(u36_1, cpu_iowq, cpu_ba4)
+
+	/* Character address counter */
+	TTL_74193(u7, low,   low,   low,   low,   low, u36_1.Q, cntclk, high)
+	TTL_74193(u5, cpu_db0, cpu_db1, cpu_db2, cpu_db3, low, u36_1.Q, u7.CARRYQ, u7.BORROWQ)
+	TTL_74193(u3, cpu_db4, cpu_db5, cpu_db6, cpu_db7, low, u36_1.Q, u5.CARRYQ, u5.BORROWQ)
+
+	TTL_74365(u6, low, ncntbenq, u7.QA, u7.QB, u7.QC, u7.QD, u5.QA, u5.QB)
+	TTL_74365(u4, low, ncntbenq, u5.QC, u5.QD, u3.QA, u3.QB, u3.QC, low)
+	ALIAS(ba0, u6.Y1)
+	ALIAS(ba1, u6.Y2)
+	ALIAS(ba2, u6.Y3)
+	ALIAS(ba3, u6.Y4)
+	ALIAS(ba4, u6.Y5)
+	ALIAS(ba5, u6.Y6)
+	ALIAS(ba6, u4.Y1)
+	ALIAS(ba7, u4.Y2)
+	ALIAS(ba8, u4.Y3)
+	ALIAS(ba9, u4.Y4)
+	ALIAS(ba10, u4.Y5)
+
+	/* Video RAM */
+	TTL_INPUT(memwq, 1)
+	TTL_INPUT(mrq, 1)
+	TTL_INPUT(ba13, 0)
+
+	TTL_7432_OR(u36_2, memwq, memwq)
+	TTL_7400_NAND(u37_2, u36_2.Q, mrq)
+	TTL_7400_NAND(u37_3, u37_2.Q, ba13)
+	TTL_7400_NAND(u37_4, u37_3.Q, ncntbenq)
+	TTL_7404_INVERT(u17_2, u4.Y5)
+	TTL_7400_NAND(u30_2, u17_2.Q, u37_4.Q)
+	TTL_7400_NAND(u37_1, u4.Y5, u37_4.Q)
+	TTL_INPUT(rwq, 1)
+
+	/* Lower 1K */
+	RAM_2102A(u22, u30_2.Q, ba0, ba1, ba2, ba3, ba4, ba5, ba6, ba7, ba8, ba9, rwq, u22.DO)
+	RAM_2102A(u23, u30_2.Q, ba0, ba1, ba2, ba3, ba4, ba5, ba6, ba7, ba8, ba9, rwq, u23.DO)
+	RAM_2102A(u24, u30_2.Q, ba0, ba1, ba2, ba3, ba4, ba5, ba6, ba7, ba8, ba9, rwq, u24.DO)
+	RAM_2102A(u25, u30_2.Q, ba0, ba1, ba2, ba3, ba4, ba5, ba6, ba7, ba8, ba9, rwq, u25.DO)
+	RAM_2102A(u26, u30_2.Q, ba0, ba1, ba2, ba3, ba4, ba5, ba6, ba7, ba8, ba9, rwq, u26.DO)
+	RAM_2102A(u27, u30_2.Q, ba0, ba1, ba2, ba3, ba4, ba5, ba6, ba7, ba8, ba9, rwq, u27.DO)
+	RAM_2102A(u28, u30_2.Q, ba0, ba1, ba2, ba3, ba4, ba5, ba6, ba7, ba8, ba9, rwq, u28.DO)
+	RAM_2102A(u29, u30_2.Q, ba0, ba1, ba2, ba3, ba4, ba5, ba6, ba7, ba8, ba9, rwq, u29.DO)
+
+	/* Upper 1K */
+	RAM_2102A(u9,  u37_1.Q, ba0, ba1, ba2, ba3, ba4, ba5, ba6, ba7, ba8, ba9, rwq, u9.DO)
+	RAM_2102A(u10, u37_1.Q, ba0, ba1, ba2, ba3, ba4, ba5, ba6, ba7, ba8, ba9, rwq, u10.DO)
+	RAM_2102A(u11, u37_1.Q, ba0, ba1, ba2, ba3, ba4, ba5, ba6, ba7, ba8, ba9, rwq, u11.DO)
+	RAM_2102A(u12, u37_1.Q, ba0, ba1, ba2, ba3, ba4, ba5, ba6, ba7, ba8, ba9, rwq, u12.DO)
+	RAM_2102A(u13, u37_1.Q, ba0, ba1, ba2, ba3, ba4, ba5, ba6, ba7, ba8, ba9, rwq, u13.DO)
+	RAM_2102A(u14, u37_1.Q, ba0, ba1, ba2, ba3, ba4, ba5, ba6, ba7, ba8, ba9, rwq, u14.DO)
+	RAM_2102A(u15, u37_1.Q, ba0, ba1, ba2, ba3, ba4, ba5, ba6, ba7, ba8, ba9, rwq, u15.DO)
+	RAM_2102A(u16, u37_1.Q, ba0, ba1, ba2, ba3, ba4, ba5, ba6, ba7, ba8, ba9, rwq, u16.DO)
+
+	TTL_INPUT(cpu_db0, 0)
+	TTL_INPUT(cpu_db1, 0)
+	TTL_INPUT(cpu_db2, 0)
+	TTL_INPUT(cpu_db3, 0)
+	TTL_INPUT(cpu_db4, 0)
+	TTL_INPUT(cpu_db5, 0)
+	TTL_INPUT(cpu_db6, 0)
+	TTL_INPUT(cpu_db7, 0)
+
+	TTL_TRISTATE(db0, u30_2.Q, u29.DO, u37_1.Q, u16.DO)
+	TTL_TRISTATE(db1, u30_2.Q, u28.DO, u37_1.Q, u15.DO)
+	TTL_TRISTATE(db2, u30_2.Q, u27.DO, u37_1.Q, u14.DO)
+	TTL_TRISTATE(db3, u30_2.Q, u26.DO, u37_1.Q, u13.DO)
+	TTL_TRISTATE(db4, u30_2.Q, u25.DO, u37_1.Q, u12.DO)
+	TTL_TRISTATE(db5, u30_2.Q, u24.DO, u37_1.Q, u11.DO)
+	TTL_TRISTATE(db6, u30_2.Q, u23.DO, u37_1.Q, u10.DO)
+	TTL_TRISTATE(db7, u30_2.Q, u22.DO, u37_1.Q, u9.DO)
+
+	/* Character generation */
+	TTL_74175(u68, dot, db0.Q, db1.Q, db2.Q, db3.Q, high) // least significant 4 bits of each character
+	TTL_AM2847(u67, lbc, u68.Q1, u68.Q2, u68.Q3, u68.Q4, sync_bus_disable_q, sync_bus_disable_q, sync_bus_disable_q, sync_bus_disable_q)
+
+	TTL_74175(u58, dot, db4.Q, db5.Q, db6.Q, db7.Q, high) // most signifcant 4 bits of each character
+	TTL_AM2847(u57, lbc, u58.Q1, u58.Q2, u58.Q3, u58.Q4, sync_bus_disable_q, sync_bus_disable_q, sync_bus_disable_q, sync_bus_disable_q)
+
+	TTL_74174(u66, ndot, u67.OUTA, u67.OUTB, u67.OUTC, u67.OUTD, u57.OUTA, u57.OUTB, high)
+	TTL_74175(u56, ndot, u57.OUTC, clr_vid_sr, u79_1.Q, u57.OUTD, high)
+	TTL_7400_NAND(u79_1, u56.Q4, clr_vid_sr)
+	ALIAS(fgbit_q, u56.Q3Q)
+
+	EPROM_2716(u78, low, low, lc20, lc21, lc22, lc23, u66.Q1, u66.Q2, u66.Q3, u66.Q4, u66.Q5, u66.Q6, u56.Q1)
+
+	TTL_74166(u77, video_clk, low, ndot, low, u78.D0, u78.D1, u78.D2, u78.D3, u78.D4, u78.D5, u78.D6, low, clr_vid_sr)
+	ALIAS(raw_dot, u77.QH)
+
+	TTL_7400_NAND(u79_4, fgbit_q, fgbit_q)
+	ALIAS(highlight, u79_4.Q)
+
+	ALIAS(video_out, raw_dot)
+
+	/* Highlight and contrast - not yet hooked up */
+	RES(R40, 160)
+	RES(R41, 270)
+	POT(R21_POT, 500)
+
+	NET_C(R40.1, V5)
+	NET_C(R40.2, R21_POT.1)
+	NET_C(raw_dot, R21_POT.1)
+	NET_C(highlight, R41.1)
+	NET_C(R41.2, R21_POT.1)
+
+	NET_C(R21_POT.3, GND)
+	NET_C(R21_POT.2, GND)
+
+NETLIST_END()
diff --git a/src/mame/machine/nl_hazelvid.h b/src/mame/machine/nl_hazelvid.h
new file mode 100644
index 0000000..ff436aa
--- /dev/null
+++ b/src/mame/machine/nl_hazelvid.h
@@ -0,0 +1,4 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+
+NETLIST_EXTERNAL(hazelvid)
diff --git a/src/mame/machine/nycaptor.cpp b/src/mame/machine/nycaptor.cpp
index 6d2645a..8a3f613 100644
--- a/src/mame/machine/nycaptor.cpp
+++ b/src/mame/machine/nycaptor.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /***************************************************************************
 
diff --git a/src/mame/machine/pitnrun.cpp b/src/mame/machine/pitnrun.cpp
index 01bc5b7..1e8ab10 100644
--- a/src/mame/machine/pitnrun.cpp
+++ b/src/mame/machine/pitnrun.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina, Pierpaolo Prazzoli
 /***************************************************************************
 
diff --git a/src/mame/machine/seibucop/seibucop.cpp b/src/mame/machine/seibucop/seibucop.cpp
index 985bba6..8b5cab3 100644
--- a/src/mame/machine/seibucop/seibucop.cpp
+++ b/src/mame/machine/seibucop/seibucop.cpp
@@ -47,8 +47,6 @@
     SD Gundam
     - stage 3 mid-boss still has the sprite garbage bug;
     - stage 4: has sprite stuck on bottom-left of screen;
-    - palette dims too much on attract / continue screen.
-      It's known that the DMA data arrangement gives same results on a real Legionnaire board, so shrug?
     Seibu Cup Soccer
     - Handles collision detection via the 130e/3bb0 macros
       130e version in this makes a sub instead of an add as last opcode, which in turn reflects with
diff --git a/src/mame/machine/seibucop/seibucop_dma.hxx b/src/mame/machine/seibucop/seibucop_dma.hxx
index c409bf5..0d5ae58 100644
--- a/src/mame/machine/seibucop/seibucop_dma.hxx
+++ b/src/mame/machine/seibucop/seibucop_dma.hxx
@@ -41,8 +41,6 @@ void raiden2cop_device::dma_palette_brightness()
 
 	TODO:
 	- Denjin Makai mode 4 is totally guessworked.
-	- SD Gundam doesn't fade colors correctly, it should have the text layer / sprites with normal gradient and the rest dimmed in most cases,
-	presumably bad RAM table or bad algorithm
 	*/
 
 	//if(dma_trigger != 0x87)
@@ -60,21 +58,28 @@ void raiden2cop_device::dma_palette_brightness()
 
 		if (pal_brightness_mode == 5)
 		{
-			bt = ((m_host_space->read_word(src + (cop_dma_adr_rel * 0x400))) & 0x7c00) >> 5;
-			bt = fade_table(bt | (pal_brightness_val ^ 0));
-			b = ((m_host_space->read_word(src)) & 0x7c00) >> 5;
-			b = fade_table(b | (pal_brightness_val ^ 0x1f));
-			pal_val = ((b + bt) & 0x1f) << 10;
-			gt = ((m_host_space->read_word(src + (cop_dma_adr_rel * 0x400))) & 0x03e0);
-			gt = fade_table(gt | (pal_brightness_val ^ 0));
-			g = ((m_host_space->read_word(src)) & 0x03e0);
-			g = fade_table(g | (pal_brightness_val ^ 0x1f));
-			pal_val |= ((g + gt) & 0x1f) << 5;
-			rt = ((m_host_space->read_word(src + (cop_dma_adr_rel * 0x400))) & 0x001f) << 5;
-			rt = fade_table(rt | (pal_brightness_val ^ 0));
-			r = ((m_host_space->read_word(src)) & 0x001f) << 5;
-			r = fade_table(r | (pal_brightness_val ^ 0x1f));
-			pal_val |= ((r + rt) & 0x1f);
+			u16 paldata = m_host_space->read_word(src);
+			if (BIT(paldata, 15))
+				pal_val = paldata; // fade me not
+			else
+			{
+				u16 targetpaldata = m_host_space->read_word(src + (cop_dma_adr_rel * 0x400));
+				bt = (targetpaldata & 0x7c00) >> 5;
+				bt = fade_table(bt | (pal_brightness_val ^ 0));
+				b = (paldata & 0x7c00) >> 5;
+				b = fade_table(b | (pal_brightness_val ^ 0x1f));
+				pal_val = ((b + bt) & 0x1f) << 10;
+				gt = (targetpaldata & 0x03e0);
+				gt = fade_table(gt | (pal_brightness_val ^ 0));
+				g = (paldata & 0x03e0);
+				g = fade_table(g | (pal_brightness_val ^ 0x1f));
+				pal_val |= ((g + gt) & 0x1f) << 5;
+				rt = (targetpaldata & 0x001f) << 5;
+				rt = fade_table(rt | (pal_brightness_val ^ 0));
+				r = (paldata & 0x001f) << 5;
+				r = fade_table(r | (pal_brightness_val ^ 0x1f));
+				pal_val |= ((r + rt) & 0x1f);
+			}
 		}
 		else if (pal_brightness_mode == 4) //Denjin Makai
 		{
diff --git a/src/mame/machine/slapfght.cpp b/src/mame/machine/slapfght.cpp
index 8da2d77..c824341 100644
--- a/src/mame/machine/slapfght.cpp
+++ b/src/mame/machine/slapfght.cpp
@@ -48,159 +48,108 @@ READ8_MEMBER(slapfght_state::tigerh_mcu_status_r)
 }
 
 
-/**************************************************************************/
+/***************************************************************************
 
-READ8_MEMBER(slapfght_state::tigerh_68705_portA_r)
-{
-	return (m_portA_out & m_ddrA) | (m_portA_in & ~m_ddrA);
-}
+    MCU port handlers (general)
 
-WRITE8_MEMBER(slapfght_state::tigerh_68705_portA_w)
-{
-	m_portA_out = data;
-}
+***************************************************************************/
 
-WRITE8_MEMBER(slapfght_state::tigerh_68705_ddrA_w)
+
+READ8_MEMBER(slapfght_state::tigerh_mcu_porta_r)
 {
-	m_ddrA = data;
+	return m_to_mcu_latch;
 }
 
-READ8_MEMBER(slapfght_state::tigerh_68705_portB_r)
+WRITE8_MEMBER(slapfght_state::tigerh_mcu_porta_w)
 {
-	return (m_portB_out & m_ddrB) | (m_portB_in & ~m_ddrB);
+	m_from_mcu_latch = data;
 }
 
-WRITE8_MEMBER(slapfght_state::tigerh_68705_portB_w)
+
+/***************************************************************************
+
+    MCU port handlers (Tiger Heli)
+
+***************************************************************************/
+
+WRITE8_MEMBER(slapfght_state::tigerh_mcu_portb_w)
 {
-	if ((m_ddrB & 0x02) && (~data & 0x02) && (m_portB_out & 0x02))
+	if ((mem_mask & 0x02) && (~data & 0x02) && (m_old_portB & 0x02))
 	{
 		if (m_main_sent)
 			m_mcu->set_input_line(0, CLEAR_LINE);
 
-		m_portA_in = m_from_main;
+		m_to_mcu_latch = m_from_main;
 		m_main_sent = false;
 	}
-	if ((m_ddrB & 0x04) && (data & 0x04) && (~m_portB_out & 0x04))
+	if ((mem_mask & 0x04) && (data & 0x04) && (~m_old_portB & 0x04))
 	{
-		m_from_mcu = m_portA_out;
+		m_from_mcu = m_from_mcu_latch;
 		m_mcu_sent = true;
 	}
 
-	m_portB_out = data;
+	m_old_portB = data;
 }
 
-WRITE8_MEMBER(slapfght_state::tigerh_68705_ddrB_w)
+READ8_MEMBER(slapfght_state::tigerh_mcu_portc_r)
 {
-	m_ddrB = data;
-}
-
-
-READ8_MEMBER(slapfght_state::tigerh_68705_portC_r)
-{
-	m_portC_in = 0;
+	uint8_t ret = 0;
 
 	if (!m_main_sent)
-		m_portC_in |= 0x01;
+		ret |= 0x01;
 	if (m_mcu_sent)
-		m_portC_in |= 0x02;
+		ret |= 0x02;
 
-	return (m_portC_out & m_ddrC) | (m_portC_in & ~m_ddrC);
+	return ret;
 }
 
-WRITE8_MEMBER(slapfght_state::tigerh_68705_portC_w)
-{
-	m_portC_out = data;
-}
-
-WRITE8_MEMBER(slapfght_state::tigerh_68705_ddrC_w)
-{
-	m_ddrC = data;
-}
-
-
-
 /***************************************************************************
 
-    Slap Fight MCU
+    MCU port handlers (Slap Fight)
 
 ***************************************************************************/
 
-READ8_MEMBER(slapfght_state::slapfight_68705_portA_r)
+WRITE8_MEMBER(slapfght_state::slapfght_mcu_portb_w)
 {
-	return (m_portA_out & m_ddrA) | (m_portA_in & ~m_ddrA);
-}
-
-WRITE8_MEMBER(slapfght_state::slapfight_68705_portA_w)
-{
-	m_portA_out = data;
-}
-
-WRITE8_MEMBER(slapfght_state::slapfight_68705_ddrA_w)
-{
-	m_ddrA = data;
-}
-
-READ8_MEMBER(slapfght_state::slapfight_68705_portB_r)
-{
-	return (m_portB_out & m_ddrB) | (m_portB_in & ~m_ddrB);
-}
-
-WRITE8_MEMBER(slapfght_state::slapfight_68705_portB_w)
-{
-	if ((m_ddrB & 0x02) && (~data & 0x02) && (m_portB_out & 0x02))
+	if ((mem_mask & 0x02) && (~data & 0x02) && (m_old_portB & 0x02))
 	{
 		if (m_main_sent)
 			m_mcu->set_input_line(0, CLEAR_LINE);
 
-		m_portA_in = m_from_main;
+		m_to_mcu_latch = m_from_main;
 		m_main_sent = false;
 	}
-	if ((m_ddrB & 0x04) && (data & 0x04) && (~m_portB_out & 0x04))
+	if ((mem_mask & 0x04) && (data & 0x04) && (~m_old_portB & 0x04))
 	{
-		m_from_mcu = m_portA_out;
+		m_from_mcu = m_from_mcu_latch;
 		m_mcu_sent = true;
 	}
-	if ((m_ddrB & 0x08) && (~data & 0x08) && (m_portB_out & 0x08))
+	if ((mem_mask & 0x08) && (~data & 0x08) && (m_old_portB & 0x08))
 	{
-		m_scrollx_lo = m_portA_out;
+		m_scrollx_lo = m_from_mcu_latch;
 	}
-	if ((m_ddrB & 0x10) && (~data & 0x10) && (m_portB_out & 0x10))
+	if ((mem_mask & 0x10) && (~data & 0x10) && (m_old_portB & 0x10))
 	{
-		m_scrollx_hi = m_portA_out;
+		m_scrollx_hi = m_from_mcu_latch;
 	}
 
-	m_portB_out = data;
+	m_old_portB = data;
 }
 
-WRITE8_MEMBER(slapfght_state::slapfight_68705_ddrB_w)
+READ8_MEMBER(slapfght_state::slapfght_mcu_portc_r)
 {
-	m_ddrB = data;
-}
+	uint8_t ret = 0;
 
-READ8_MEMBER(slapfght_state::slapfight_68705_portC_r)
-{
-	m_portC_in = 0;
-
-	if (m_main_sent)
-		m_portC_in |= 0x01;
-	if (!m_mcu_sent)
-		m_portC_in |= 0x02;
-
-	return (m_portC_out & m_ddrC) | (m_portC_in & ~m_ddrC);
-}
+	if (!m_main_sent)
+		ret |= 0x01;
+	if (m_mcu_sent)
+		ret |= 0x02;
 
-WRITE8_MEMBER(slapfght_state::slapfight_68705_portC_w)
-{
-	m_portC_out = data;
-}
+	ret ^= 0x3; // inverted logic compared to tigerh
 
-WRITE8_MEMBER(slapfght_state::slapfight_68705_ddrC_w)
-{
-	m_ddrC = data;
+	return ret;
 }
 
-
-
 /***************************************************************************
 
     Get Star MCU simulation :(
diff --git a/src/mame/machine/theglobp.cpp b/src/mame/machine/theglobp.cpp
deleted file mode 100644
index 8c153ec..0000000
--- a/src/mame/machine/theglobp.cpp
+++ /dev/null
@@ -1,258 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nicola Salmoria
-/***************************************************************************
-
-  machine.c
-
-  Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
-  I/O ports)
-
-  The Glob protection description:
-
-  The Glob is designed to run on modified Pacman hardware.  It contains
-  two graphics ROMs at 5E and 5F, but contains code ROMs on a daughterboard
-  similar in concept to Ms. Pacman.  However, these code ROMs are decrypted
-  through additional circuitry.  The daughterboard was encased in epoxy.
-
-  Here's a description of the protection as best as I can give it.
-
-  1)  The decrypted D0 bit fed to the CPU is simply an inversion of the
-      D5 bit from the code ROMs.
-  2)  The decrypted D1 bit fed to the CPU is simply an inversion of the
-      D2 bit from the code ROMs.
-  3)  The other 6 data bits are decrypted by a 10H8 PAL.  The PAL also
-      takes as input a 4-bit counter.  The counter is incremented and
-      decremented as follows:
-      - the Z-80 command IN($xx) where xx is an odd number decrements the
-        counter; an even number increments the counter.
-        Ex:  IN($64) would increment the counter, IN($6B) would decrement
-        the counter.
-  4)  The PAL output also contains the two ROM enable lines used to enable
-      the two encrypted code ROMs.  As long as the system is working
-      correctly, these ROMs will always be enabled.
-
-  As it so happens, only four counter values are ever used, which is
-  fortunate because the PAL only contains signals to enable the ROMs for
-  those four counter values.  The valid counter values are $8, $9, $A, and
-  $B.  The counter's intial value is $A, which is set by jumpers on the
-  daughterboard.  Following is a description of the resulting decryptions
-  for these four counter states.
-
-  COUNTER       ENCRYPTED   DECRYPTED
-                  VALUE       VALUE
-
-                DDDDDDDD    DDDDDDDD
-                76543210    76543210
-
-  Counter = 8:  abcdefgh    EAhBDgFC
-  Counter = 9:  abcdefgh    FAgeDBFC
-  Counter = A:  abcdefgh    EHDBagFC
-  Counter = B:  abcdefgh    GHDEaBFC
-
-  In the above diagram, capital letters represent inverted bits.  Notice
-  that bits D2 and D5 are the same independent of counter state, this is
-  because these bits are not decrypted by the PAL.
-
-
-  In the code below, all four of these decryption patterns are used to
-  decrypt the entire code ROMs before execution.  This is done for speed,
-  since we can then just bankswitch between the decrypted code sets on
-  each IN($xx) command, as opposed to dynamically decrypting every byte.
-
-  - Mike Balfour (mab22 at po.cwru.edu)
-
-***************************************************************************/
-
-#include "emu.h"
-#include "includes/pacman.h"
-
-
-void pacman_state::theglobp_decrypt_rom_8()
-{
-	int oldbyte,inverted_oldbyte,newbyte;
-	int mem;
-	uint8_t *RAM;
-
-	RAM = memregion("maincpu")->base();
-
-
-	for (mem=0;mem<0x4000;mem++)
-	{
-		oldbyte = RAM[mem];
-		inverted_oldbyte = ~oldbyte;
-
-		/*  Note: D2 is inverted and connected to D1, D5 is inverted and
-		    connected to D0.  The other six data bits are converted by a
-		    PAL10H8 driven by the counter. */
-
-		/* Direct inversion */
-		newbyte  = (inverted_oldbyte & 0x04) >> 1;
-		newbyte |= (inverted_oldbyte & 0x20) >> 5;
-		/* PAL */
-		newbyte |= (oldbyte & 0x01) << 5;
-		newbyte |= (oldbyte & 0x02) << 1;
-		newbyte |= (inverted_oldbyte & 0x08) << 4;
-		newbyte |= (inverted_oldbyte & 0x10) >> 1;
-		newbyte |= (inverted_oldbyte & 0x40) >> 2;
-		newbyte |= (inverted_oldbyte & 0x80) >> 1;
-
-		RAM[mem + 0x10000] = newbyte;
-	}
-
-	return;
-}
-
-
-void pacman_state::theglobp_decrypt_rom_9()
-{
-	int oldbyte,inverted_oldbyte,newbyte;
-	int mem;
-	uint8_t *RAM;
-
-	RAM = memregion("maincpu")->base();
-
-	for (mem=0;mem<0x4000;mem++)
-	{
-		oldbyte = RAM[mem];
-		inverted_oldbyte = ~oldbyte;
-
-		/*  Note: D2 is inverted and connected to D1, D5 is inverted and
-		    connected to D0.  The other six data bits are converted by a
-		    PAL10H8 driven by the counter. */
-
-		/* Direct inversion */
-		newbyte  = (inverted_oldbyte & 0x04) >> 1;
-		newbyte |= (inverted_oldbyte & 0x20) >> 5;
-		/* PAL */
-		newbyte |= (oldbyte & 0x01) << 5;
-		newbyte |= (inverted_oldbyte & 0x02) << 6;
-		newbyte |= (oldbyte & 0x08) << 1;
-		newbyte |= (inverted_oldbyte & 0x10) >> 1;
-		newbyte |= (inverted_oldbyte & 0x40) >> 4;
-		newbyte |= (inverted_oldbyte & 0x80) >> 1;
-
-		RAM[mem + 0x14000] = newbyte;
-	}
-
-	return;
-}
-
-void pacman_state::theglobp_decrypt_rom_A()
-{
-	int oldbyte,inverted_oldbyte,newbyte;
-	int mem;
-	uint8_t *RAM;
-
-	RAM = memregion("maincpu")->base();
-
-	for (mem=0;mem<0x4000;mem++)
-	{
-		oldbyte = RAM[mem];
-		inverted_oldbyte = ~oldbyte;
-
-		/*  Note: D2 is inverted and connected to D1, D5 is inverted and
-		    connected to D0.  The other six data bits are converted by a
-		    PAL10H8 driven by the counter. */
-
-		/* Direct inversion */
-		newbyte  = (inverted_oldbyte & 0x04) >> 1;
-		newbyte |= (inverted_oldbyte & 0x20) >> 5;
-		/* PAL */
-		newbyte |= (inverted_oldbyte & 0x01) << 6;
-		newbyte |= (oldbyte & 0x02) << 1;
-		newbyte |= (inverted_oldbyte & 0x08) << 4;
-		newbyte |= (inverted_oldbyte & 0x10) << 1;
-		newbyte |= (inverted_oldbyte & 0x40) >> 2;
-		newbyte |= (oldbyte & 0x80) >> 4;
-
-		RAM[mem + 0x18000] = newbyte;
-	}
-
-	return;
-}
-
-void pacman_state::theglobp_decrypt_rom_B()
-{
-	int oldbyte,inverted_oldbyte,newbyte;
-	int mem;
-	uint8_t *RAM;
-
-	RAM = memregion("maincpu")->base();
-
-	for (mem=0;mem<0x4000;mem++)
-	{
-		oldbyte = RAM[mem];
-		inverted_oldbyte = ~oldbyte;
-
-		/*  Note: D2 is inverted and connected to D1, D5 is inverted and
-		    connected to D0.  The other six data bits are converted by a
-		    PAL10H8 driven by the counter. */
-
-		/* Direct inversion */
-		newbyte  = (inverted_oldbyte & 0x04) >> 1;
-		newbyte |= (inverted_oldbyte & 0x20) >> 5;
-		/* PAL */
-		newbyte |= (inverted_oldbyte & 0x01) << 6;
-		newbyte |= (inverted_oldbyte & 0x02) << 6;
-		newbyte |= (oldbyte & 0x08) << 1;
-		newbyte |= (inverted_oldbyte & 0x10) << 1;
-		newbyte |= (inverted_oldbyte & 0x40) >> 4;
-		newbyte |= (oldbyte & 0x80) >> 4;
-
-		RAM[mem + 0x1C000] = newbyte;
-	}
-
-	return;
-}
-
-
-READ8_MEMBER(pacman_state::theglobp_decrypt_rom )
-{
-	if (offset & 0x01)
-	{
-		m_counter = (m_counter - 1) & 0x0F;
-	}
-	else
-	{
-		m_counter = (m_counter + 1) & 0x0F;
-	}
-
-	switch(m_counter)
-	{
-		case 0x08:  membank ("bank1")->set_entry (0);        break;
-		case 0x09:  membank ("bank1")->set_entry (1);        break;
-		case 0x0A:  membank ("bank1")->set_entry (2);        break;
-		case 0x0B:  membank ("bank1")->set_entry (3);        break;
-		default:
-			logerror("Invalid counter = %02X\n",m_counter);
-			break;
-	}
-
-	return 0;
-}
-
-
-MACHINE_START_MEMBER(pacman_state,theglobp)
-{
-	uint8_t *RAM = memregion("maincpu")->base();
-
-	/* While the PAL supports up to 16 decryption methods, only four
-	    are actually used in the PAL.  Therefore, we'll take a little
-	    memory overhead and decrypt the ROMs using each method in advance. */
-	theglobp_decrypt_rom_8();
-	theglobp_decrypt_rom_9();
-	theglobp_decrypt_rom_A();
-	theglobp_decrypt_rom_B();
-
-	membank("bank1")->configure_entries(0, 4, &RAM[0x10000], 0x4000);
-
-	save_item(NAME(m_counter));
-}
-
-
-MACHINE_RESET_MEMBER(pacman_state,theglobp)
-{
-	/* The initial state of the counter is 0x0A */
-	m_counter = 0x0A;
-	membank("bank1")->set_entry(2);
-}
diff --git a/src/mame/machine/tnzs.cpp b/src/mame/machine/tnzs.cpp
index 5359a4d..58a8559 100644
--- a/src/mame/machine/tnzs.cpp
+++ b/src/mame/machine/tnzs.cpp
@@ -18,13 +18,9 @@
 #include "cpu/mcs48/mcs48.h"
 #include "includes/tnzs.h"
 
-
-
-READ8_MEMBER(tnzs_state::mcu_tnzs_r)
+READ8_MEMBER(tnzs_mcu_state::mcu_r)
 {
-	uint8_t data;
-
-	data = m_mcu->upi41_master_r(space, offset & 1);
+	uint8_t data = m_mcu->upi41_master_r(space, offset & 1);
 	space.device().execute().yield();
 
 //  logerror("PC %04x: read %02x from mcu $c00%01x\n", space.device().safe_pcbase(), data, offset);
@@ -32,19 +28,18 @@ READ8_MEMBER(tnzs_state::mcu_tnzs_r)
 	return data;
 }
 
-WRITE8_MEMBER(tnzs_state::mcu_tnzs_w)
+WRITE8_MEMBER(tnzs_mcu_state::mcu_w)
 {
 //  logerror("PC %04x: write %02x to mcu $c00%01x\n", space.device().safe_pcbase(), data, offset);
 
 	m_mcu->upi41_master_w(space, offset & 1, data);
 }
 
-
-READ8_MEMBER(tnzs_state::tnzs_port1_r)
+READ8_MEMBER(tnzs_mcu_state::mcu_port1_r)
 {
 	int data = 0;
 
-	switch (m_input_select & 0x0f)
+	switch (m_input_select)
 	{
 		case 0x0a:  data = m_in2->read(); break;
 		case 0x0c:  data = m_in0->read(); break;
@@ -57,43 +52,33 @@ READ8_MEMBER(tnzs_state::tnzs_port1_r)
 	return data;
 }
 
-READ8_MEMBER(tnzs_state::tnzs_port2_r)
+READ8_MEMBER(tnzs_mcu_state::mcu_port2_r)
 {
-	int data = m_in2->read();
-
-//  logerror("I8742:%04x  Read %02x from port 2\n", space.device().safe_pcbase(), data);
-
-	return data;
+	return m_in2->read();
 }
 
-WRITE8_MEMBER(tnzs_state::tnzs_port2_w)
+WRITE8_MEMBER(tnzs_mcu_state::mcu_port2_w)
 {
-//  logerror("I8742:%04x  Write %02x to port 2\n", space.device().safe_pcbase(), data);
-
-	machine().bookkeeping().coin_lockout_w(0, (data & 0x40));
-	machine().bookkeeping().coin_lockout_w(1, (data & 0x80));
+	machine().bookkeeping().coin_lockout_w(0, (data & 0x40) != 0 ? m_lockout_level : !m_lockout_level);
+	machine().bookkeeping().coin_lockout_w(1, (data & 0x80) != 0 ? m_lockout_level : !m_lockout_level);
 	machine().bookkeeping().coin_counter_w(0, (~data & 0x10));
 	machine().bookkeeping().coin_counter_w(1, (~data & 0x20));
 
-	m_input_select = data;
+	m_input_select = data & 0xf;
 }
 
-
-
-READ8_MEMBER(tnzs_state::arknoid2_sh_f000_r)
+// TODO: Eliminate this once arknoid2 MCU is dumped
+READ8_MEMBER(tnzs_base_state::analog_r)
 {
-//  logerror("PC %04x: read input %04x\n", space.device().safe_pc(), 0xf000 + offset);
-
-	int val = ((offset / 2) ? m_an2 : m_an1).read_safe(0);
+	uint16_t val = ((offset & 2) ? m_an2 : m_an1).read_safe(0);
 
 	if (offset & 1)
-		return ((val >> 8) & 0xff);
-	else
-		return val & 0xff;
-}
+		return val >> 8;
 
+	return val;
+}
 
-void tnzs_state::mcu_reset(  )
+void arknoid2_state::mcu_reset()
 {
 	m_mcu_initializing = 3;
 	m_mcu_coinage_init = 0;
@@ -108,7 +93,7 @@ void tnzs_state::mcu_reset(  )
 	m_mcu_command = 0;
 }
 
-void tnzs_state::mcu_handle_coins( int coin )
+void arknoid2_state::mcu_handle_coins( int coin )
 {
 	/* The coin inputs and coin counters are managed by the i8742 mcu. */
 	/* Here we simulate it. */
@@ -179,12 +164,68 @@ void tnzs_state::mcu_handle_coins( int coin )
 	m_insertcoin = coin;
 }
 
+/*********************************
+
+TNZS sync bug kludge
+
+In all TNZS versions there is code like this:
+
+0C5E: ld   ($EF10),a
+0C61: ld   a,($EF10)
+0C64: inc  a
+0C65: ret  nz
+0C66: jr   $0C61
+
+which is sometimes executed by the main cpu when it writes to shared RAM a
+command for the second CPU. The intended purpose of the code is to wait an
+acknowledge from the sub CPU: the sub CPU writes FF to the same location
+after reading the command.
+
+However the above code is wrong. The "ret nz" instruction means that the
+loop will be exited only when the contents of $EF10 are *NOT* $FF!!
+On the real board, this casues little harm: the main CPU will just write
+the command, read it back and, since it's not $FF, return immediately. There
+is a chance that the command might go lost, but this will cause no major
+harm, the worse that can happen is that the background tune will not change.
+
+In MAME, however, since CPU interleaving is not perfect, it can happen that
+the main CPU ends its timeslice after writing to EF10 but before reading it
+back. In the meantime, the sub CPU will run, read the command and write FF
+there - therefore causing the main CPU to enter an endless loop.
+
+Unlike the usual sync problems in MAME, which can be fixed by increasing the
+interleave factor, in this case increasing it will actually INCREASE the
+chance of entering the endless loop - because it will increase the chances of
+the main CPU ending its timeslice at the wrong moment.
+
+So what we do here is catch writes by the main CPU to the RAM location, and
+process them using a timer, in order to
+a) force a resync of the two CPUs
+b) make sure the main CPU will be the first one to run after the location is
+   changed
+
+Since the answer from the sub CPU is ignored, we don't even need to boost
+interleave.
+
+*********************************/
+
+/*
+TIMER_CALLBACK_MEMBER(tnzs_base_state::kludge_callback)
+{
+    tnzs_sharedram[0x0f10] = param;
+}
+
+WRITE8_MEMBER(tnzs_base_state::tnzs_sync_kludge_w)
+{
+    machine().scheduler().synchronize(timer_expired_delegate(FUNC(tnzs_base_state::kludge_callback),this), data);
+}
+*/
 
-READ8_MEMBER(tnzs_state::mcu_arknoid2_r)
+READ8_MEMBER(arknoid2_state::mcu_r)
 {
 	static const char mcu_startup[] = "\x55\xaa\x5a";
 
-//  logerror("PC %04x: read mcu %04x\n", space.device().safe_pc(), 0xc000 + offset);
+	//logerror("PC %04x: read mcu %04x\n", space.device().safe_pc(), 0xc000 + offset);
 
 	if (offset == 0)
 	{
@@ -241,11 +282,11 @@ READ8_MEMBER(tnzs_state::mcu_arknoid2_r)
 	}
 }
 
-WRITE8_MEMBER(tnzs_state::mcu_arknoid2_w)
+WRITE8_MEMBER(arknoid2_state::mcu_w)
 {
 	if (offset == 0)
 	{
-//      logerror("PC %04x: write %02x to mcu %04x\n", space.device().safe_pc(), data, 0xc000 + offset);
+		//logerror("PC %04x: write %02x to mcu %04x\n", space.device().safe_pc(), data, 0xc000 + offset);
 		if (m_mcu_command == 0x41)
 		{
 			m_mcu_credits = (m_mcu_credits + data) & 0xff;
@@ -262,7 +303,7 @@ WRITE8_MEMBER(tnzs_state::mcu_arknoid2_w)
 		0x80: release coin lockout (issued only in test mode)
 		during initialization, a sequence of 4 bytes sets coin/credit settings
 		*/
-//      logerror("PC %04x: write %02x to mcu %04x\n", space.device().safe_pc(), data, 0xc000 + offset);
+		//logerror("PC %04x: write %02x to mcu %04x\n", space.device().safe_pc(), data, 0xc000 + offset);
 
 		if (m_mcu_initializing)
 		{
@@ -285,452 +326,162 @@ WRITE8_MEMBER(tnzs_state::mcu_arknoid2_w)
 	}
 }
 
-
-READ8_MEMBER(tnzs_state::mcu_extrmatn_r)
+INTERRUPT_GEN_MEMBER(arknoid2_state::mcu_interrupt)
 {
-	static const char mcu_startup[] = "\x5a\xa5\x55";
-
-//  logerror("PC %04x: read mcu %04x\n", space.device().safe_pc(), 0xc000 + offset);
+	int coin = ((m_coin1->read() & 1) << 0);
+	coin |= ((m_coin2->read() & 1) << 1);
+	coin |= ((m_in2->read() & 3) << 2);
+	coin ^= 0x0c;
+	mcu_handle_coins(coin);
 
-	if (offset == 0)
-	{
-		/* if the mcu has just been reset, return startup code */
-		if (m_mcu_initializing)
-		{
-			m_mcu_initializing--;
-			return mcu_startup[2 - m_mcu_initializing];
-		}
-
-		switch (m_mcu_command)
-		{
-			case 0x01:
-				return m_in0->read() ^ 0xff;    /* player 1 joystick + buttons */
-
-			case 0x02:
-				return m_in1->read() ^ 0xff;    /* player 2 joystick + buttons */
-
-			case 0x1a:
-				return (m_coin1->read() | (m_coin2->read() << 1));
-
-			case 0x21:
-				return m_in2->read() & 0x0f;
-
-			case 0x41:
-				return m_mcu_credits;
-
-			case 0xa0:
-				/* Read the credit counter */
-				if (m_mcu_reportcoin & 0x08)
-				{
-					m_mcu_initializing = 3;
-					return 0xee;    /* tilt */
-				}
-				else return m_mcu_credits;
-
-			case 0xa1:
-				/* Read the credit counter or the inputs */
-				if (m_mcu_readcredits == 0)
-				{
-					m_mcu_readcredits = 1;
-					if (m_mcu_reportcoin & 0x08)
-					{
-						m_mcu_initializing = 3;
-						return 0xee;    /* tilt */
-//                      return 0x64;    /* theres a reset input somewhere */
-					}
-					else return m_mcu_credits;
-				}
-				/* buttons */
-				else return ((m_in0->read() & 0xf0) | (m_in1->read() >> 4)) ^ 0xff;
-
-			default:
-				logerror("error, unknown mcu command\n");
-				/* should not happen */
-				return 0xff;
-		}
-	}
-	else
-	{
-		/*
-		status bits:
-		0 = mcu is ready to send data (read from c000)
-		1 = mcu has read data (from c000)
-		2 = unused
-		3 = unused
-		4-7 = coin code
-		      0 = nothing
-		      1,2,3 = coin switch pressed
-		      e = tilt
-		*/
-		if (m_mcu_reportcoin & 0x08) return 0xe1;   /* tilt */
-		if (m_mcu_reportcoin & 0x01) return 0x11;   /* coin 1 (will trigger "coin inserted" sound) */
-		if (m_mcu_reportcoin & 0x02) return 0x21;   /* coin 2 (will trigger "coin inserted" sound) */
-		if (m_mcu_reportcoin & 0x04) return 0x31;   /* coin 3 (will trigger "coin inserted" sound) */
-		return 0x01;
-	}
+	device.execute().set_input_line(0, HOLD_LINE);
 }
 
-WRITE8_MEMBER(tnzs_state::mcu_extrmatn_w)
+void arknoid2_state::machine_reset()
 {
-	if (offset == 0)
-	{
-//      logerror("PC %04x: write %02x to mcu %04x\n", space.device().safe_pc(), data, 0xc000 + offset);
-		if (m_mcu_command == 0x41)
-		{
-			m_mcu_credits = (m_mcu_credits + data) & 0xff;
-		}
-	}
-	else
-	{
-		/*
-		0xa0: read number of credits
-		0xa1: read number of credits, then buttons
-		0x01: read player 1 joystick + buttons
-		0x02: read player 2 joystick + buttons
-		0x1a: read coin switches
-		0x21: read service & tilt switches
-		0x4a+0x41: add value to number of credits
-		0x84: coin 1 lockout (issued only in test mode)
-		0x88: coin 2 lockout (issued only in test mode)
-		0x80: release coin lockout (issued only in test mode)
-		during initialization, a sequence of 4 bytes sets coin/credit settings
-		*/
-
-//      logerror("PC %04x: write %02x to mcu %04x\n", space.device().safe_pc(), data, 0xc000 + offset);
-
-		if (m_mcu_initializing)
-		{
-			/* set up coin/credit settings */
-			m_mcu_coinage[m_mcu_coinage_init++] = data;
-			if (m_mcu_coinage_init == 4)
-				m_mcu_coinage_init = 0; /* must not happen */
-		}
-
-		if (data == 0xa1)
-			m_mcu_readcredits = 0;  /* reset input port number */
-
-		/* Dr Toppel decrements credits differently. So handle it */
-		if ((data == 0x09) && (m_mcu_type == MCU_DRTOPPEL || m_mcu_type == MCU_PLUMPOP))
-			m_mcu_credits = (m_mcu_credits - 1) & 0xff;     /* Player 1 start */
-		if ((data == 0x18) && (m_mcu_type == MCU_DRTOPPEL || m_mcu_type == MCU_PLUMPOP))
-			m_mcu_credits = (m_mcu_credits - 2) & 0xff;     /* Player 2 start */
+	/* initialize the mcu simulation */
+	mcu_reset();
 
-		m_mcu_command = data;
-	}
+	m_mcu_readcredits = 0;
+	m_insertcoin = 0;
 }
 
-
-
-/*********************************
-
-TNZS sync bug kludge
-
-In all TNZS versions there is code like this:
-
-0C5E: ld   ($EF10),a
-0C61: ld   a,($EF10)
-0C64: inc  a
-0C65: ret  nz
-0C66: jr   $0C61
-
-which is sometimes executed by the main cpu when it writes to shared RAM a
-command for the second CPU. The intended purpose of the code is to wait an
-acknowledge from the sub CPU: the sub CPU writes FF to the same location
-after reading the command.
-
-However the above code is wrong. The "ret nz" instruction means that the
-loop will be exited only when the contents of $EF10 are *NOT* $FF!!
-On the real board, this casues little harm: the main CPU will just write
-the command, read it back and, since it's not $FF, return immediately. There
-is a chance that the command might go lost, but this will cause no major
-harm, the worse that can happen is that the background tune will not change.
-
-In MAME, however, since CPU interleaving is not perfect, it can happen that
-the main CPU ends its timeslice after writing to EF10 but before reading it
-back. In the meantime, the sub CPU will run, read the command and write FF
-there - therefore causing the main CPU to enter an endless loop.
-
-Unlike the usual sync problems in MAME, which can be fixed by increasing the
-interleave factor, in this case increasing it will actually INCREASE the
-chance of entering the endless loop - because it will increase the chances of
-the main CPU ending its timeslice at the wrong moment.
-
-So what we do here is catch writes by the main CPU to the RAM location, and
-process them using a timer, in order to
-a) force a resync of the two CPUs
-b) make sure the main CPU will be the first one to run after the location is
-   changed
-
-Since the answer from the sub CPU is ignored, we don't even need to boost
-interleave.
-
-*********************************/
-
-/*
-TIMER_CALLBACK_MEMBER(tnzs_state::kludge_callback)
+void kageki_state::machine_reset()
 {
-    tnzs_sharedram[0x0f10] = param;
+	tnzs_base_state::machine_reset();
+	m_csport_sel = 0;
 }
 
-WRITE8_MEMBER(tnzs_state::tnzs_sync_kludge_w)
+void tnzs_base_state::machine_start()
 {
-    machine().scheduler().synchronize(timer_expired_delegate(FUNC(tnzs_state::kludge_callback),this), data);
-}
-*/
-
-
+	uint8_t *sub = memregion("sub")->base();
 
-DRIVER_INIT_MEMBER(tnzs_state,plumpop)
-{
-	m_mcu_type = MCU_PLUMPOP;
-}
+	m_bank2 = 0;
+	m_mainbank->set_bank(2);
 
-DRIVER_INIT_MEMBER(tnzs_state,extrmatn)
-{
-	m_mcu_type = MCU_EXTRMATN;
-}
+	m_subbank->configure_entries(0, 4, &sub[0x08000], 0x2000);
+	m_subbank->set_entry(m_bank2);
 
-DRIVER_INIT_MEMBER(tnzs_state,arknoid2)
-{
-	m_mcu_type = MCU_ARKANOID;
+	save_item(NAME(m_bank2));
 }
 
-DRIVER_INIT_MEMBER(tnzs_state,drtoppel)
+void arknoid2_state::machine_start()
 {
-	m_mcu_type = MCU_DRTOPPEL;
-
-	/* drtoppel writes to the palette RAM area even if it has PROMs! We have to patch it out. */
-	m_maincpu->space(AS_PROGRAM).nop_write(0xf800, 0xfbff);
+	tnzs_base_state::machine_start();
+	save_item(NAME(m_mcu_readcredits));
+	save_item(NAME(m_insertcoin));
+	save_item(NAME(m_mcu_initializing));
+	save_item(NAME(m_mcu_coinage_init));
+	save_item(NAME(m_mcu_coinage));
+	save_item(NAME(m_mcu_coins_a));
+	save_item(NAME(m_mcu_coins_b));
+	save_item(NAME(m_mcu_credits));
+	save_item(NAME(m_mcu_reportcoin));
+	save_item(NAME(m_mcu_command));
 }
 
-DRIVER_INIT_MEMBER(tnzs_state,chukatai)
+void kageki_state::machine_start()
 {
-	m_mcu_type = MCU_CHUKATAI;
+	tnzs_base_state::machine_start();
+	save_item(NAME(m_csport_sel));
 }
 
-DRIVER_INIT_MEMBER(tnzs_state,tnzs)
+void kabukiz_state::machine_start()
 {
-	m_mcu_type = MCU_TNZS;
-	/* we need to install a kludge to avoid problems with a bug in the original code */
-//  m_maincpu->space(AS_PROGRAM).install_write_handler(0xef10, 0xef10, write8_delegate(FUNC(tnzs_state::tnzs_sync_kludge_w), this));
+	tnzs_base_state::machine_start();
+	uint8_t *sound = memregion("audiocpu")->base();
+	m_audiobank->configure_entries(0, 8, &sound[0x00000], 0x4000);
 }
 
-DRIVER_INIT_MEMBER(tnzs_state,tnzsb)
+WRITE8_MEMBER(tnzs_base_state::ramrom_bankswitch_w)
 {
-	m_mcu_type = MCU_NONE_TNZSB;
-
-	/* we need to install a kludge to avoid problems with a bug in the original code */
-//  m_maincpu->space(AS_PROGRAM).install_write_handler(0xef10, 0xef10, write8_delegate(FUNC(tnzs_state::tnzs_sync_kludge_w), this));
-}
+//  logerror("PC %04x: writing %02x to bankswitch\n", space.device().safe_pc(),data);
 
-DRIVER_INIT_MEMBER(tnzs_state,kabukiz)
-{
-	uint8_t *SOUND = memregion("audiocpu")->base();
-	m_mcu_type = MCU_NONE_KABUKIZ;
+	/* bit 4 resets the second CPU */
+	if (data & 0x10)
+		m_subcpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
+	else
+		m_subcpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
 
-	m_audiobank->configure_entries(0, 8, &SOUND[0x00000], 0x4000);
+	/* bits 0-2 select RAM/ROM bank */
+	m_mainbank->set_bank(data & 0x07);
 }
 
-DRIVER_INIT_MEMBER(tnzs_state,insectx)
+WRITE8_MEMBER(arknoid2_state::bankswitch1_w)
 {
-	m_mcu_type = MCU_NONE_INSECTX;
-
-	/* this game has no mcu, replace the handler with plain input port handlers */
-	m_subcpu->space(AS_PROGRAM).install_read_port(0xc000, 0xc000, "IN0" );
-	m_subcpu->space(AS_PROGRAM).install_read_port(0xc001, 0xc001, "IN1" );
-	m_subcpu->space(AS_PROGRAM).install_read_port(0xc002, 0xc002, "IN2" );
+	tnzs_base_state::bankswitch1_w(space, offset, data, mem_mask);
+	if (data & 0x04)
+		mcu_reset();
 }
 
-DRIVER_INIT_MEMBER(tnzs_state,kageki)
+WRITE8_MEMBER(insectx_state::bankswitch1_w)
 {
-	m_mcu_type = MCU_NONE_KAGEKI;
+	tnzs_base_state::bankswitch1_w(space, offset, data, mem_mask);
+	machine().bookkeeping().coin_lockout_w(0, (~data & 0x04));
+	machine().bookkeeping().coin_lockout_w(1, (~data & 0x08));
+	machine().bookkeeping().coin_counter_w(0, (data & 0x10));
+	machine().bookkeeping().coin_counter_w(1, (data & 0x20));
 }
 
-
-READ8_MEMBER(tnzs_state::tnzs_mcu_r)
+WRITE8_MEMBER(tnzsb_state::bankswitch1_w) // kabukiz_state
 {
-	switch (m_mcu_type)
-	{
-		case MCU_TNZS:
-		case MCU_CHUKATAI:
-			return mcu_tnzs_r(space, offset);
-		case MCU_ARKANOID:
-			return mcu_arknoid2_r(space, offset);
-		case MCU_EXTRMATN:
-		case MCU_DRTOPPEL:
-		case MCU_PLUMPOP:
-			return mcu_extrmatn_r(space, offset);
-		default:
-			return 0xff;
-	}
+	tnzs_base_state::bankswitch1_w(space, offset, data, mem_mask);
+	machine().bookkeeping().coin_lockout_w(0, (~data & 0x10));
+	machine().bookkeeping().coin_lockout_w(1, (~data & 0x20));
+	machine().bookkeeping().coin_counter_w(0, (data & 0x04));
+	machine().bookkeeping().coin_counter_w(1, (data & 0x08));
 }
 
-WRITE8_MEMBER(tnzs_state::tnzs_mcu_w)
+WRITE8_MEMBER(kageki_state::bankswitch1_w)
 {
-	switch (m_mcu_type)
-	{
-		case MCU_TNZS:
-		case MCU_CHUKATAI:
-			mcu_tnzs_w(space, offset, data);
-			break;
-		case MCU_ARKANOID:
-			mcu_arknoid2_w(space, offset, data);
-			break;
-		case MCU_EXTRMATN:
-		case MCU_DRTOPPEL:
-		case MCU_PLUMPOP:
-			mcu_extrmatn_w(space, offset, data);
-			break;
-		default:
-			break;
-	}
+	tnzs_base_state::bankswitch1_w(space, offset, data, mem_mask);
+	machine().bookkeeping().coin_lockout_global_w((~data & 0x20));
+	machine().bookkeeping().coin_counter_w(0, (data & 0x04));
+	machine().bookkeeping().coin_counter_w(1, (data & 0x08));
 }
 
-INTERRUPT_GEN_MEMBER(tnzs_state::arknoid2_interrupt)
+WRITE8_MEMBER(tnzs_mcu_state::bankswitch1_w)
 {
-	int coin;
-
-	switch (m_mcu_type)
-	{
-		case MCU_ARKANOID:
-		case MCU_EXTRMATN:
-		case MCU_DRTOPPEL:
-		case MCU_PLUMPOP:
-			coin  = 0;
-			coin |= ((m_coin1->read() & 1) << 0);
-			coin |= ((m_coin2->read() & 1) << 1);
-			coin |= ((m_in2->read() & 3) << 2);
-			coin ^= 0x0c;
-			mcu_handle_coins(coin);
-			break;
-		default:
-			break;
-	}
-
-	device.execute().set_input_line(0, HOLD_LINE);
+	tnzs_base_state::bankswitch1_w(space, offset, data, mem_mask);
+	if ((data & 0x04) != 0 && m_mcu != nullptr)
+		m_mcu->set_input_line(INPUT_LINE_RESET, PULSE_LINE);
 }
 
-MACHINE_RESET_MEMBER(tnzs_state,tnzs)
+WRITE8_MEMBER(tnzs_base_state::bankswitch1_w)
 {
-	/* initialize the mcu simulation */
-	switch (m_mcu_type)
-	{
-		case MCU_ARKANOID:
-		case MCU_EXTRMATN:
-		case MCU_DRTOPPEL:
-		case MCU_PLUMPOP:
-			mcu_reset();
-			break;
-		default:
-			break;
-	}
+//  logerror("PC %04x: writing %02x to bankswitch 1\n", space.device().safe_pc(),data);
 
-	m_kageki_csport_sel = 0;
-	m_input_select = 0;
-	m_mcu_readcredits = 0;  // this might belong to mcu_reset
-	m_insertcoin = 0;       // this might belong to mcu_reset
+	/* bits 0-1 select ROM bank */
+	m_bank2 = data & 0x03;
+	m_subbank->set_entry(m_bank2);
 }
 
-MACHINE_RESET_MEMBER(tnzs_state,jpopnics)
+void jpopnics_state::machine_reset()
 {
-	m_mcu_type = -1;
+	tnzs_base_state::machine_reset();
 }
 
-
-MACHINE_START_MEMBER(tnzs_state,tnzs_common)
+WRITE8_MEMBER(jpopnics_state::subbankswitch_w)
 {
-	uint8_t *SUB = memregion("sub")->base();
-
-	m_subbank->configure_entries(0, 4, &SUB[0x08000], 0x2000);
-	m_subbank->set_entry(m_bank2);
-
-	m_bank2 = 0;
-	m_mainbank->set_bank(2);
-
-	save_item(NAME(m_bank2));
+	/* bits 0-1 select ROM bank */
+	m_subbank->set_entry(data & 0x03);
 }
 
-MACHINE_START_MEMBER(tnzs_state,tnzs)
+WRITE8_MEMBER(tnzsb_state::sound_command_w)
 {
-	MACHINE_START_CALL_MEMBER( tnzs_common );
-
-	save_item(NAME(m_kageki_csport_sel));
-	save_item(NAME(m_input_select));
-	save_item(NAME(m_mcu_readcredits));
-	save_item(NAME(m_insertcoin));
-	save_item(NAME(m_mcu_initializing));
-	save_item(NAME(m_mcu_coinage_init));
-	save_item(NAME(m_mcu_coinage));
-	save_item(NAME(m_mcu_coins_a));
-	save_item(NAME(m_mcu_coins_b));
-	save_item(NAME(m_mcu_credits));
-	save_item(NAME(m_mcu_reportcoin));
-	save_item(NAME(m_mcu_command));
-
+	m_soundlatch->write(space, offset, data);
+	m_audiocpu->set_input_line_and_vector(0, HOLD_LINE, 0xff);
 }
 
-
-WRITE8_MEMBER(tnzs_state::tnzs_ramrom_bankswitch_w)
+/* handler called by the 2203 emulator when the internal timers cause an IRQ */
+WRITE_LINE_MEMBER(tnzsb_state::ym2203_irqhandler)
 {
-//  logerror("PC %04x: writing %02x to bankswitch\n", space.device().safe_pc(),data);
-
-	/* bit 4 resets the second CPU */
-	if (data & 0x10)
-		m_subcpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
-	else
-		m_subcpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
-
-	/* bits 0-2 select RAM/ROM bank */
-	m_mainbank->set_bank(data & 0x07);
+	m_audiocpu->set_input_line(INPUT_LINE_NMI, state ? ASSERT_LINE : CLEAR_LINE);
 }
 
-WRITE8_MEMBER(tnzs_state::tnzs_bankswitch1_w)
+WRITE8_MEMBER(kabukiz_state::sound_bank_w)
 {
-//  logerror("PC %04x: writing %02x to bankswitch 1\n", space.device().safe_pc(),data);
-
-	switch (m_mcu_type)
-	{
-		case MCU_TNZS:
-		case MCU_CHUKATAI:
-				/* bit 2 resets the mcu */
-				if (data & 0x04)
-				{
-					if (m_mcu != nullptr && m_mcu->type() == I8742)
-						m_mcu->set_input_line(INPUT_LINE_RESET, PULSE_LINE);
-				}
-				/* Coin count and lockout is handled by the i8742 */
-				break;
-		case MCU_NONE_INSECTX:
-				machine().bookkeeping().coin_lockout_w(0, (~data & 0x04));
-				machine().bookkeeping().coin_lockout_w(1, (~data & 0x08));
-				machine().bookkeeping().coin_counter_w(0, (data & 0x10));
-				machine().bookkeeping().coin_counter_w(1, (data & 0x20));
-				break;
-		case MCU_NONE_TNZSB:
-		case MCU_NONE_KABUKIZ:
-				machine().bookkeeping().coin_lockout_w(0, (~data & 0x10));
-				machine().bookkeeping().coin_lockout_w(1, (~data & 0x20));
-				machine().bookkeeping().coin_counter_w(0, (data & 0x04));
-				machine().bookkeeping().coin_counter_w(1, (data & 0x08));
-				break;
-		case MCU_NONE_KAGEKI:
-				machine().bookkeeping().coin_lockout_global_w((~data & 0x20));
-				machine().bookkeeping().coin_counter_w(0, (data & 0x04));
-				machine().bookkeeping().coin_counter_w(1, (data & 0x08));
-				break;
-		case MCU_ARKANOID:
-		case MCU_EXTRMATN:
-		case MCU_DRTOPPEL:
-		case MCU_PLUMPOP:
-				/* bit 2 resets the mcu */
-				if (data & 0x04)
-					mcu_reset();
-				break;
-		default:
-				break;
-	}
-
-	/* bits 0-1 select ROM bank */
-	m_bank2 = data & 0x03;
-	m_subbank->set_entry(m_bank2);
+	// to avoid the write when the sound chip is initialized
+	if (data != 0xff)
+		m_audiobank->set_entry(data & 0x07);
 }
diff --git a/src/mame/machine/toaplan1.cpp b/src/mame/machine/toaplan1.cpp
index 3ecf716..8e79026 100644
--- a/src/mame/machine/toaplan1.cpp
+++ b/src/mame/machine/toaplan1.cpp
@@ -12,32 +12,6 @@
 #include "includes/toaplan1.h"
 
 
-
-/* List of possible regions for coinage (for games with unemulated sound CPU) */
-enum {
-	TOAPLAN1_REGION_JAPAN=0,
-	TOAPLAN1_REGION_US,
-	TOAPLAN1_REGION_WORLD,
-	TOAPLAN1_REGION_OTHER
-};
-
-static const uint8_t toaplan1_coins_for_credit[TOAPLAN1_REGION_OTHER+1][2][4] =
-{
-	{ { 1, 1, 2, 2 }, { 1, 1, 2, 2 } }, /* TOAPLAN1_REGION_JAPAN */
-	{ { 1, 1, 2, 2 }, { 1, 1, 2, 2 } }, /* TOAPLAN1_REGION_US */
-	{ { 1, 2, 3, 4 }, { 1, 1, 1, 1 } }, /* TOAPLAN1_REGION_WORLD */
-	{ { 1, 1, 1, 1 }, { 1, 1, 1, 1 } }  /* TOAPLAN1_REGION_OTHER */
-};
-
-static const uint8_t toaplan1_credits_for_coin[TOAPLAN1_REGION_OTHER+1][2][4] =
-{
-	{ { 1, 2, 1, 3 }, { 1, 2, 1, 3 } }, /* TOAPLAN1_REGION_JAPAN */
-	{ { 1, 2, 1, 3 }, { 1, 2, 1, 3 } }, /* TOAPLAN1_REGION_US */
-	{ { 1, 1, 1, 1 }, { 2, 3, 4, 6 } }, /* TOAPLAN1_REGION_WORLD */
-	{ { 1, 1, 1, 1 }, { 1, 1, 1, 1 } }, /* TOAPLAN1_REGION_OTHER */
-};
-
-
 INTERRUPT_GEN_MEMBER(toaplan1_state::toaplan1_interrupt)
 {
 	if (m_intenable)
@@ -179,109 +153,6 @@ READ16_MEMBER(toaplan1_state::samesame_port_6_word_r)
 	return (0x80 | ioport("TJUMP")->read()) & 0xff;
 }
 
-READ16_MEMBER(toaplan1_state::vimana_system_port_r)
-{
-	static const uint8_t vimana_region[16] =
-	{
-		TOAPLAN1_REGION_JAPAN, TOAPLAN1_REGION_US   , TOAPLAN1_REGION_WORLD, TOAPLAN1_REGION_JAPAN,
-		TOAPLAN1_REGION_JAPAN, TOAPLAN1_REGION_JAPAN, TOAPLAN1_REGION_JAPAN, TOAPLAN1_REGION_US   ,
-		TOAPLAN1_REGION_JAPAN, TOAPLAN1_REGION_OTHER, TOAPLAN1_REGION_OTHER, TOAPLAN1_REGION_OTHER,
-		TOAPLAN1_REGION_OTHER, TOAPLAN1_REGION_OTHER, TOAPLAN1_REGION_OTHER, TOAPLAN1_REGION_JAPAN
-	};
-
-	int data, p, r, d, slot, reg, dsw;
-
-	slot = -1;
-	d = ioport("DSWA")->read();
-	r = ioport("TJUMP")->read();
-	p = ioport("SYSTEM")->read();
-	m_vimana_latch ^= p;
-	data = (m_vimana_latch & p);
-
-	/* simulate the mcu keeping track of credits based on region and coinage settings */
-	/* latch so it doesn't add more than one coin per keypress */
-	if (d & 0x04)   /* "test mode" ON */
-	{
-		m_vimana_coins[0] = m_vimana_coins[1] = 0;
-		m_vimana_credits = 0;
-	}
-	else            /* "test mode" OFF */
-	{
-		if (data & 0x02)      /* TILT */
-		{
-			m_vimana_coins[0] = m_vimana_coins[1] = 0;
-			m_vimana_credits = 0;
-		}
-		if (data & 0x01)      /* SERVICE1 */
-		{
-			m_vimana_credits++ ;
-		}
-		if (data & 0x08)      /* COIN1 */
-		{
-			slot = 0;
-		}
-		if (data & 0x10)      /* COIN2 */
-		{
-			slot = 1 ;
-		}
-
-		if (slot != -1)
-		{
-			reg = vimana_region[r];
-			dsw = (d & 0xf0) >> (4 + 2 * slot);
-			m_vimana_coins[slot]++;
-			if (m_vimana_coins[slot] >= toaplan1_coins_for_credit[reg][slot][dsw])
-			{
-				m_vimana_credits += toaplan1_credits_for_coin[reg][slot][dsw];
-				m_vimana_coins[slot] -= toaplan1_coins_for_credit[reg][slot][dsw];
-			}
-			machine().bookkeeping().coin_counter_w(slot, 1);
-			machine().bookkeeping().coin_counter_w(slot, 0);
-		}
-
-		if (m_vimana_credits >= 9)
-			m_vimana_credits = 9;
-	}
-
-	machine().bookkeeping().coin_lockout_global_w((m_vimana_credits >= 9));
-
-	m_vimana_latch = p;
-
-	return p & 0xffff;
-}
-
-READ16_MEMBER(toaplan1_state::vimana_mcu_r)
-{
-	int data = 0 ;
-	switch (offset)
-	{
-		case 0:  data = 0xff; break;
-		case 1:  data = 0x00; break;
-		case 2:
-		{
-			data = m_vimana_credits;
-			break;
-		}
-	}
-	return data & 0xff;
-}
-
-WRITE16_MEMBER(toaplan1_state::vimana_mcu_w)
-{
-	switch (offset)
-	{
-		case 0: break;
-		case 1: break;
-		case 2:
-			if (ACCESSING_BITS_0_7)
-			{
-				m_vimana_credits = data & 0xff;
-				machine().bookkeeping().coin_lockout_global_w((m_vimana_credits >= 9));
-			}
-			break;
-	}
-}
-
 READ16_MEMBER(toaplan1_state::toaplan1_shared_r)
 {
 	return m_sharedram[offset] & 0xff;
@@ -398,9 +269,6 @@ MACHINE_RESET_MEMBER(toaplan1_state,demonwld)
 MACHINE_RESET_MEMBER(toaplan1_state,vimana)
 {
 	MACHINE_RESET_CALL_MEMBER(toaplan1);
-	m_vimana_coins[0] = m_vimana_coins[1] = 0;
-	m_vimana_credits = 0;
-	m_vimana_latch = 0;
 	m_maincpu->set_reset_callback(write_line_delegate(FUNC(toaplan1_state::toaplan1_reset_callback),this));
 }
 
@@ -421,10 +289,3 @@ void toaplan1_state::demonwld_driver_savestate()
 	machine().save().register_postload(save_prepost_delegate(FUNC(toaplan1_state::demonwld_restore_dsp), this));
 }
 
-void toaplan1_state::vimana_driver_savestate()
-{
-	save_item(NAME(m_vimana_coins[0]));
-	save_item(NAME(m_vimana_coins[1]));
-	save_item(NAME(m_vimana_credits));
-	save_item(NAME(m_vimana_latch));
-}
diff --git a/src/mame/machine/xbox.cpp b/src/mame/machine/xbox.cpp
index d0ce516..4405046 100644
--- a/src/mame/machine/xbox.cpp
+++ b/src/mame/machine/xbox.cpp
@@ -14,13 +14,66 @@
 #include "debugger.h"
 #include "debug/debugcon.h"
 #include "debug/debugcmd.h"
-#include "includes/chihiro.h"
+#include "includes/xbox_nv2a.h"
 #include "includes/xbox.h"
 #include "includes/xbox_usb.h"
 
 #define LOG_PCI
 //#define LOG_AUDIO
 
+const xbox_base_state::debugger_constants xbox_base_state::debugp[] = {
+	{ 0x66232714, {0x8003aae0, 0x5c, 0x1c, 0x28, 0x210, 8, 0x28, 0x1c} },
+	{ 0x49d8055a, {0x8003aae0, 0x5c, 0x1c, 0x28, 0x210, 8, 0x28, 0x1c} }
+};
+
+int xbox_base_state::find_bios_index(running_machine &mach)
+{
+	u8 sb = mach.driver_data()->system_bios();
+	return sb;
+}
+
+bool xbox_base_state::find_bios_hash(running_machine &mach, int bios, uint32_t &crc32)
+{
+	uint32_t crc = 0;
+	const std::vector<rom_entry> &rev = mach.root_device().rom_region_vector();
+
+	for (rom_entry re : rev)
+	{
+		if ((re.flags() & ROMENTRY_TYPEMASK) == ROMENTRYTYPE_ROM)
+		{
+			if ((re.flags() & ROM_BIOSFLAGSMASK) == ROM_BIOS(bios + 1))
+			{
+				const std::string &h = re.hashdata();
+				util::hash_collection hc(h.c_str());
+				if (hc.crc(crc) == true)
+				{
+					crc32 = crc;
+					return true;
+				}
+			}
+		}
+	}
+	return false;
+}
+
+void xbox_base_state::find_debug_params(running_machine &mach)
+{
+	uint32_t crc;
+	int sb;
+
+	sb = (int)find_bios_index(machine());
+	debugc_bios = debugp;
+	if (find_bios_hash(machine(), sb - 1, crc) == true)
+	{
+		for (int n = 0; n < 2; n++)
+			if (debugp[n].id == crc)
+			{
+				debugc_bios = &debugp[n];
+				break;
+			}
+	}
+}
+
 void xbox_base_state::dump_string_command(int ref, int params, const char **param)
 {
 	debugger_cpu &cpu = machine().debugger().cpu();
@@ -50,6 +103,7 @@ void xbox_base_state::dump_string_command(int ref, int params, const char **para
 	con.printf("MaximumLength %d word\n", maximumlength);
 	con.printf("Buffer %08X byte* ", buffer);
 
+	// limit the number of characters to avoid flooding
 	if (length > 256)
 		length = 256;
 
@@ -221,28 +275,57 @@ void xbox_base_state::curthread_command(int ref, int params, const char **param)
 	offs_t address;
 
 	uint64_t fsbase = m_maincpu->state_int(44); // base of FS register
-	address = (offs_t)fsbase + 0x28;
+	address = (offs_t)fsbase + (offs_t)debugc_bios->parameter[7-1];
 	if (!m_maincpu->translate(AS_PROGRAM, TRANSLATE_READ_DEBUG, address))
 	{
 		con.printf("Address is unmapped.\n");
 		return;
 	}
-	address = (offs_t)fsbase + 0x28;
+	address = (offs_t)fsbase + (offs_t)debugc_bios->parameter[7-1];
 
 	uint32_t kthrd = cpu.read_dword(space, address, true);
 	con.printf("Current thread is %08X\n", kthrd);
-	address = (offs_t)kthrd + 0x1c;
+	address = (offs_t)(kthrd + debugc_bios->parameter[8-1]);
 	uint32_t topstack = cpu.read_dword(space, address, true);
 	con.printf("Current thread stack top is %08X\n", topstack);
-	address = (offs_t)kthrd + 0x28;
+	address = (offs_t)(kthrd + debugc_bios->parameter[4-1]);
 	uint32_t tlsdata = cpu.read_dword(space, address, true);
 	if (tlsdata == 0)
-		address = (offs_t)topstack - 0x210 - 8;
+		address = (offs_t)(topstack - debugc_bios->parameter[5-1] - debugc_bios->parameter[6-1]);
 	else
-		address = (offs_t)tlsdata - 8;
+		address = (offs_t)(tlsdata - debugc_bios->parameter[6-1]);
 	con.printf("Current thread function is %08X\n", cpu.read_dword(space, address, true));
 }
 
+void xbox_base_state::threadlist_command(int ref, int params, const char **param)
+{
+	address_space &space = m_maincpu->space();
+	debugger_cpu &cpu = machine().debugger().cpu();
+	debugger_console &con = machine().debugger().console();
+
+	con.printf("Pri. _KTHREAD   Stack  Function\n");
+	con.printf("-------------------------------\n");
+	for (int pri = 0; pri < 16; pri++)
+	{
+		uint32_t curr = debugc_bios->parameter[1 - 1] + pri * 8;
+		uint32_t next = cpu.read_dword(space, curr, true);
+
+		while ((next != curr) && (next != 0))
+		{
+			uint32_t kthrd = next - debugc_bios->parameter[2 - 1];
+			uint32_t topstack = cpu.read_dword(space, kthrd + debugc_bios->parameter[3 - 1], true);
+			uint32_t tlsdata = cpu.read_dword(space, kthrd + debugc_bios->parameter[4 - 1], true);
+			uint32_t function;
+			if (tlsdata == 0)
+				function = cpu.read_dword(space, topstack - debugc_bios->parameter[5 - 1] - debugc_bios->parameter[6 - 1], true);
+			else
+				function = cpu.read_dword(space, tlsdata - debugc_bios->parameter[6 - 1], true);
+			con.printf(" %02d  %08x %08x %08x\n", pri, kthrd, topstack, function);
+			next = cpu.read_dword(space, next, true);
+		}
+	}
+}
+
 void xbox_base_state::generate_irq_command(int ref, int params, const char **param)
 {
 	uint64_t irq;
@@ -372,6 +455,7 @@ void xbox_base_state::help_command(int ref, int params, const char **param)
 	con.printf("  xbox dump_dpc,<address> -- Dump _KDPC object at <address>\n");
 	con.printf("  xbox dump_timer,<address> -- Dump _KTIMER object at <address>\n");
 	con.printf("  xbox curthread -- Print information about current thread\n");
+	con.printf("  xbox threadlist -- list of currently active threads\n");
 	con.printf("  xbox irq,<number> -- Generate interrupt with irq number 0-15\n");
 	con.printf("  xbox nv2a_combiners -- Toggle use of register combiners\n");
 	con.printf("  xbox waitvblank -- Toggle support for wait vblank method\n");
@@ -397,6 +481,8 @@ void xbox_base_state::xbox_debug_commands(int ref, int params, const char **para
 		dump_timer_command(ref, params - 1, param + 1);
 	else if (strcmp("curthread", param[0]) == 0)
 		curthread_command(ref, params - 1, param + 1);
+	else if (strcmp("threadlist", param[0]) == 0)
+		threadlist_command(ref, params - 1, param + 1);
 	else if (strcmp("irq", param[0]) == 0)
 		generate_irq_command(ref, params - 1, param + 1);
 	else if (strcmp("nv2a_combiners", param[0]) == 0)
@@ -1114,6 +1200,7 @@ ADDRESS_MAP_END
 
 void xbox_base_state::machine_start()
 {
+	find_debug_params(machine());
 	nvidia_nv2a = std::make_unique<nv2a_renderer>(machine());
 	memset(pic16lc_buffer, 0, sizeof(pic16lc_buffer));
 	pic16lc_buffer[0] = 'B';
diff --git a/src/mame/machine/xbox_usb.cpp b/src/mame/machine/xbox_usb.cpp
index a838846..96d18b1 100644
--- a/src/mame/machine/xbox_usb.cpp
+++ b/src/mame/machine/xbox_usb.cpp
@@ -6,7 +6,7 @@
 #include "machine/idectrl.h"
 #include "video/poly.h"
 #include "bitmap.h"
-#include "includes/chihiro.h"
+#include "includes/xbox_nv2a.h"
 #include "includes/xbox.h"
 #include "includes/xbox_usb.h"
 
diff --git a/src/mame/mame.lst b/src/mame/mame.lst
index 141feb2..38d44e1 100644
--- a/src/mame/mame.lst
+++ b/src/mame/mame.lst
@@ -904,6 +904,7 @@ spinlbrkj                       // (c) 1990 V-System Co. (Japan)
 spinlbrku                       // (c) 1990 V-System Co. (US)
 svolly91                        // (c) 1991 Video System Co. (Japan)
 turbofrc                        // (c) 1991 Video System Co.
+turbofrcu                       // (c) 1991 Video System Co. (US)
 wbbc97                          // (c) 1997 Comad
 
 @source:age_candy.cpp
@@ -3144,6 +3145,7 @@ sc1zep                          // Zeppelin (Bellfruit)
 
 @source:bfm_sc2.cpp
 gldncrwn                        // 1997
+gldncrwnhop                     // 1997
 paradice                        // 1995
 pokio                           // 1994
 pyramid                         // 1996
@@ -9611,6 +9613,7 @@ cocoe                           // Color Computer (Extended BASIC 1.0)
 cp400                           // Prologica CP400
 lzcolor64                       // Digiponto LZ Color64
 mx1600                          // Dynacom MX-1600
+t4426                           // Terco T4426 CNC programming station
 
 @source:coco3.cpp
 coco3                           // Color Computer 3 (NTSC)
@@ -10696,12 +10699,14 @@ ddribblep                       // GX690 (c) 1986
 bttf_a20                        //
 bttf_a21                        //
 bttf_a27                        //
+bttf_a28                        //
 bttf_g27                        //
 kiko_a10                        //
 lwar_a81                        //
 lwar_a83                        //
 lwar_e90                        //
 mnfb_c27                        //
+mnfb_c29                        //
 play_a24                        //
 poto_a29                        //
 poto_a32                        //
@@ -11990,6 +11995,7 @@ sd1                             // 1990 SD-1
 sd132                           // 1991 SD-1 32
 sq1                             // 1990 SQ-1
 sqrack                          // 1990 SQ-Rack
+sq2                             // 1991 SQ-2
 vfx                             // 1989 VFX
 vfxsd                           // 1989 VFX-SD
 
@@ -12109,6 +12115,7 @@ galsnewa                        // (c) 1990 Kaneko
 galsnewj                        // (c) 1990 Kaneko
 galsnewk                        // (c) 1990 Kaneko
 missmw96                        // (c) 1996 Comad
+missw02                         // (c) 2002 Daigom
 missw96                         // (c) 1996 Comad
 missw96a                        // (c) 1996 Comad
 missw96b                        // (c) 1996 Comad
@@ -12202,6 +12209,9 @@ fb01                            // 1986 FB-01
 @source:fc100.cpp
 fc100                           //
 
+ at source:fccpu20.cpp
+fccpu20
+
 @source:fccpu30.cpp
 fccpu30
 fccpu30x
@@ -12265,6 +12275,7 @@ cscfr                           // * French
 cscg                            // * German
 cscsp                           // * Spanish
 fdes2000                        //
+fdes2000d                       //
 fdes2100d                       //
 feasbu                          // EAS: Elite A/S Challenger (Budapest program, English)
 feasbufr                        // * French
@@ -12783,6 +12794,7 @@ jumpbug                         // (c) 1981 Rock-ola
 jumpbugb                        // (c) 1981 Sega
 jungsub                         // bootleg
 kamakazi3                       // Video Games (UK) Ltd., hack or bootleg?
+kamikazp                        // bootleg (Potomac Games)
 kingball                        // (c) 1980 Namco
 kingballj                       // (c) 1980 Namco
 kong                            // (c) Taito (Brazil) - rewrite of Donkey Kong
@@ -12790,11 +12802,11 @@ levers                          // (c) 1983 Rock-ola
 losttomb                        // (c) 1982 Stern
 losttombh                       // (c) 1982 Stern
 luctoday                        // 1980 Sigma
+mltiwars                        // bootleg (Gayton Games)
 monsterz                        // (c) 1982 Nihon (Arcade TV Game List - P.102, Left, 20 from top)
 moonal2                         // [1980] Nichibutsu
 moonal2b                        // [1980] Nichibutsu
 moonaln                         // [Nichibutsu] (Karateco license) or hack
-kamikazp                        // bootleg (Potomac Games)
 mooncmw                         // bootleg
 mooncptc                        // bootleg (Petaco S.A.)
 mooncreg                        // bootleg
@@ -13267,6 +13279,7 @@ rushatck                        // GX577 (c) 1985
 
 @source:gcpinbal.cpp
 gcpinbal                        // (c) 1994 Excellent System
+pwrflip                         // (c) 1994 Excellent System
 
 @source:gei.cpp
 amuse                           // (c) 1982 Greyhound Electronics
@@ -13338,7 +13351,7 @@ pc                              // 1987 PC with CGA
 pcega                           // 1987 PC with EGA
 pcherc                          // 1987 PC with Hercules (for testing hercules)
 pcmda                           // 1987 PC with MDA
-xtvga                           // 198? PC-XT (VGA, MF2 Keyboard)
+pcvga                           // 198? PC-XT (VGA, MF2 Keyboard)
 
 @source:ggconnie.cpp
 ggconnie                        // (c) ???? Capcom
@@ -13374,6 +13387,7 @@ gkigtez                         //
 gkkey                           //
 igtsc                           //
 ms72c                           //
+ms3                             //
 
 @source:gladiatr.cpp
 gcastle                         // QB  (c) 1986 Taito Corporation (prototype?)
@@ -14187,6 +14201,7 @@ funrlgl                         // Mattel
 h2hbaskb                        // Coleco
 lightfgt                        // Milton Bradley
 plus1                           // Milton Bradley
+qkracer                         // National Semiconductor
 
 @source:hh_hmcs40.cpp
 alnattck                        // Coleco
@@ -14407,6 +14422,7 @@ lemnangl                        // (c) 1990 Home Data
 mhgaiden                        // (c) 1987 Home Data
 mirderby                        // (c) 1988 Home Data?
 mjclinic                        // (c) 1988 Home Data
+mjclinica                       // (c) 1988 Home Data
 mjhokite                        // (c) 1988 Home Data
 mjikaga                         // (c) 1991 Mitchell
 mjkinjas                        // (c) 1991 Home Data
@@ -14796,10 +14812,11 @@ ironhors                        // GX560 (c) 1986
 @source:isbc.cpp
 isbc286                         //
 isbc2861                        //
+isbc28612                       //
 isbc86                          //
 rpc86                           //
-isbc8605            //
-isbc8630            //
+isbc8605                        //
+isbc8630                        //
 
 @source:isbc8010.cpp
 isbc8010                        //
@@ -16928,7 +16945,8 @@ gtrfrksa                        // 1999 - Guitar Freaks (GQ886 VER. AAC)
 gtrfrksj                        // 1999 - Guitar Freaks (GQ886 VER. JAC)
 gtrfrksu                        // 1999 - Guitar Freaks (GQ886 VER. UAC)
 gunmania                        // 2000 - GunMania (GL906 VER. JAA)
-hndlchmp                        // 1997 - Handle Champ (GQ710 VER. JAA)
+strgchmp                        // 1997 - Steering Champ (GQ710 VER. UAA)
+hndlchmp                        // 1997 - Handle Champ (GQ710 VER. JAB)
 hypbbc2p                        // 1999 - Hyper Bishi Bashi Champ - 2 Player (GX908 1999/08/24 VER. JAA)
 hypbbc2pk                       // 1999 - Hyper Bishi Bashi Champ - 2 Player (GX908 1999/08/24 VER. KAA)
 hyperbbc                        // 1998 - Hyper Bishi Bashi (GQ876 VER. EAA)
@@ -16998,9 +17016,9 @@ tricktrp                        // GX771 (c) 1987
 cavenger                        // 8106 (c) 1981
 dorodon                         // Falcon
 dorodon2                        // Falcon
-ladybgb2                        // bootleg
 ladybug                         // 8110 (c) 1981
 ladybugb                        // bootleg
+ladybugb2                       // bootleg
 snapjack                        // ???? (c)
 
 @source:ladyfrog.cpp
@@ -17312,6 +17330,9 @@ trojanj                         // 4/1986 (c) 1986 (Japan)
 trojanr                         // 4/1986 (c) 1986 + Romstar
 fball                        //
 
+ at source:lwriter.cpp
+lwriter                         // Apple LaserWriter
+
 @source:lynx.cpp
 lynx                            // Atari Lynx Handheld
 
@@ -17620,6 +17641,9 @@ magictga                        // (c) 199? Acclaim
 @source:magmax.cpp
 magmax                          // (c) 1985
 
+ at source:magnum.cpp
+magnum                          //
+
 @source:magtouch.cpp
 magtouch                        // (c) 1995
 
@@ -19750,7 +19774,6 @@ spyhunt2                        // (c) 1987
 spyhunt2a                       // (c) 1987
 trisport                        // (c) 1989
 xenophob                        // (c) 1987
-zwackery                        // (c) 1984
 
 @source:meadows.cpp
 bowl3d                          // [1978?]
@@ -20527,6 +20550,7 @@ overrev                         // 1997.09 Over Rev (Revision A)
 overrevb                        // 1997.09 Over Rev (Revision B)
 pltkids                         // 1999.03 Pilot Kids (Revision A)
 pltkidsa                        // 1999.03 Pilot Kids
+rascot2                         // 1997.?? Royal Ascot II
 rchase2                         // 1995.06 Rail Chase 2 (Revision A)
 schamp                          // 1996.05 Sonic Championship (USA)
 segawski                        // 1997.09 Sega Water Ski (Japan, Revision A)
@@ -20535,14 +20559,16 @@ sgt24h                          // 1996.07 Super GT 24h
 skisuprg                        // 1996.12 Sega Ski Super G
 skytargt                        // 1995.10 Sky Target
 srallyc                         // 1995.02 Sega Rally Championship TWIN (Revision C)
-srallyca                        // 1995.02 Sega Rally Championship DX (Revision A)
 srallycb                        // 1995.02 Sega Rally Championship TWIN (Revision B)
+srallycdx                       // 1995.02 Sega Rally Championship DX (Revision A)
+srallycdxa                      // 1995.02 Sega Rally Championship DX
 stcc                            // 1996.09 Sega Touring Car Championship
 stcca                           // 1996.09 Sega Touring Car Championship (Revision A)
 stccb                           // 1996.09 Sega Touring Car Championship
 topskatr                        // 1997.05 Top Skater (Export, Revision A)
 topskatrj                       // 1997.05 Top Skater (Japan)
 topskatru                       // 1997.05 Top Skater (USA, Revision A)
+topskatruo                      // 1997.05 Top Skater (USA)
 vcop                            // 1994.09 Virtua Cop (Revision B)
 vcop2                           // 1995.09 Virtua Cop 2
 vcopa                           // 1994.09 Virtua Cop (Revision A)
@@ -20603,6 +20629,7 @@ vs215o                          // 1997.06 Virtua Striker 2
 vs298                           // 1998.05 Virtua Striker 2 ver.98
 vs29815                         // 1998.05 Virtua Striker 2 ver.98
 vs299                           // 1998.12 Virtual Striker 2 ver.99
+vs29915                         // 1999.?? Virtual Striker 2 ver.99 (Step 1.5)
 vs299a                          // 1999.?? Virtual Striker 2 ver.99 (rev A)
 vs299b                          // 1999.?? Virtual Striker 2 ver.99 (rev B)
 vs2v991                         // 1999.?? Virtual Striker 2 ver.99.1
@@ -20620,7 +20647,8 @@ mole                            // (c) 1982 Yachiyo Electronics, Ltd.
 molecula                        //
 
 @source:momoko.cpp
-momoko                          // (c) 1986 Jaleco
+momoko                          // (c) 1986 Jaleco (Japanese text)
+momokoe                         // (c) 1986 Jaleco (English text)
 
 @source:monacogp.cpp
 monacogp                        // (c) 1980 Sega
@@ -28836,6 +28864,7 @@ quizkofk                        // 0080 (c) 1995 Saurus
 ragnagrd                        // 0218 (c) 1996 Saurus
 rbff1                           // 0095 (c) 1995 SNK
 rbff1a                          // 0095 (c) 1995 SNK
+rbff1k                          // 0095 (c) 1995 SNK
 rbff2                           // 0240 (c) 1998 SNK
 rbff2h                          // 0240 (c) 1998 SNK
 rbff2k                          // 0140 Censored Korean release of rbff2
@@ -29378,6 +29407,7 @@ crushs                          // 1981 bootleg
 ctrpllrp                        // hack
 dremshpr                        // (c) 1982 Sanritsu
 drivfrcp                        // (c) 1984 Shinkai Inc. (Magic Eletronics Inc. license)
+eeekk                           // (c) 1984 Epos Corporation
 eggor                           // (c) 1983 Telko
 eyes                            // (c) 1982 Digitrex Techstar + "Rockola presents"
 eyes2                           // (c) 1982 Techstar + "Rockola presents"
@@ -29577,6 +29607,8 @@ ssam88s                         //
 sx16                            // Sanyo SX-16
 zdsupers                        //
 ncrpc4i                         // NCR PC4i
+laser_turbo_xt                  // 1988 VTech Laser Turbo XT
+laser_xt3                       // 1989 VTech Laser XT/3
 
 @source:pc100.cpp
 pc100                           //
@@ -30298,6 +30330,7 @@ pexm007p                        // (c) 1997 IGT - International Game Technology
 pexm008p                        // (c) 1997 IGT - International Game Technology
 pexm009p                        // (c) 1997 IGT - International Game Technology
 pexm013p                        // (c) 1997 IGT - International Game Technology
+pexmp011                        // (c) 1997 IGT - International Game Technology
 pexmp013                        // (c) 1997 IGT - International Game Technology
 pexmp017                        // (c) 1997 IGT - International Game Technology
 pexmp017a                       // (c) 1997 IGT - International Game Technology
@@ -30501,6 +30534,13 @@ orleg2                          // (c) 2007
 orleg2o                         //
 orleg2oa                        //
 
+ at source:pgm3.cpp
+kov3hd
+kov3hd104
+kov3hd103
+kov3hd102
+kov3hd101
+
 @source:phantom.cpp
 fphantom                        //
 
@@ -31363,6 +31403,7 @@ qixa                            // LK  (c) 1981 Taito America Corporation
 qixb                            // LK  (c) 1981 Taito America Corporation
 qixo                            // LK  (c) 1981 Taito America Corporation
 sdungeon                        // SD  (c) 1981 Taito America Corporation
+sdungeona                       // SD  (c) 1981 Taito America Corporation
 slither                         // (c) 1982 Century II
 slithera                        // (c) 1982 Century II
 zookeep                         // ZA  (c) 1982 Taito America Corporation
@@ -31455,6 +31496,7 @@ raiden                          // (c) 1990 Seibu Kaihatsu
 raidena                         // (c) 1990 Seibu Kaihatsu
 raidenb                         // (c) 1990 Seibu Kaihatsu
 raidenk                         // (c) 1990 Seibu Kaihatsu + IBL Corporation license
+raidenkb                        // (c) bootleg
 raident                         // (c) 1990 Seibu Kaihatsu + Liang HWA Electronics license
 raidenu                         // (c) 1990 Seibu Kaihatsu + Fabtek license
 raidenua                        // (c) 1990 Seibu Kaihatsu + Fabtek license
@@ -32874,7 +32916,8 @@ sonicp                          // 1993.?? Sonic the Hedgehog (proto, Japan)
 spidman                         // 1991.?? Spiderman (World)
 spidmanj                        // 1991.09 Spiderman (Japan)
 spidmanu                        // 1991.09 Spiderman (US)
-svf                             // 1994.?? Super Visual Football
+svf                             // 1994.?? Super Visual Football (Rev A)
+svfo                            // 1994.?? Super Visual Football
 svs                             // 1994.?? Super Visual Soccer
 titlef                          // 1993.?? Title Fight (World)
 titlefj                         // 1993.03 Title Fight (Japan)
@@ -33093,6 +33136,7 @@ qzkklogy                        // (c) 1992 Tecmo
 rezon                           // (c) 1991 Allumer
 rezont                          // (c) 1991 Allumer / Taito
 setaroul                        // UF   (c) 19?? Seta / Visco
+simpsonjr                       // bootleg of J. J. Squawkers by Daigom
 sokonuke                        // (c) 1995 Sammy Industries
 stg                             // (c) 1991 Athena / Tecmo
 superbar                        // (c) 1994 Promat (not genuine seta hardware, but based on thunderl code)
@@ -34643,6 +34687,7 @@ chopliftbl                      // bootleg (S2)
 chopliftu                       // 834-5795 (c) 1985, (c) 1982 Dan Gorlin (S2)
 dakkochn                        // 836-6483 (S2)
 flicky                          // (c) 1984 (S1)
+flickya                         // (c) 1984 (S1)
 flickyo                         // (c) 1984 (S1)
 flickys1                        // (c) 1984 (S1)
 flickys2                        // (c) 1984 (S1)
@@ -35127,8 +35172,9 @@ landgearj                       // 1996.?? E17 (c) 1996 Taito Corporation (Japan
 landgearja                      // 1996.03 E17 (c) 1996 Taito Corporation (Japan) - Ver 3.0 J
 sidebs                          // 1996.07 E23 (c) 1996 Taito Corporation (Japan) - Ver 2.7 J
 sidebs2                         // 1997.07 E38 (c) 1997 Taito Corporation (World) - Ver 2.6 OK
-sidebs2j                        // 1997.07 E38 (c) 1997 Taito Corporation (Japan) - Ver 2.4 J
+sidebs2j                        // 1997.07 E38 (c) 1997 Taito Corporation (Japan) - Ver 3.1 J
 sidebs2u                        // 1997.07 E38 (c) 1997 Taito Corporation (US) - Ver 2.6 A
+sidebs2ja                       // 1997.07 E38 (c) 1997 Taito Corporation (Japan) - Ver 2.4 J
 sidebsja                        // 1996.07 E23 (c) 1996 Taito Corporation (Japan) - Ver 2.6 J
 sidebsjb                        // 1996.07 E23 (c) 1996 Taito Corporation (Japan) - Ver 2.5 J
 
@@ -35769,6 +35815,7 @@ tnzsj                           // B53 (c) 1988 Taito Corporation (Japan) (new p
 tnzsjo                          // B53 (c) 1988 Taito Corporation (Japan) (old pcb)
 tnzsuo                          // B53 (c) 1988 Taito America Corporation (US) (old pcb)
 tnzso                           // B53 (c) 1988 Taito Corporation Japan (World) (old pcb)
+tnzsoa                          // B53?(c) 1988 Taito Corporation Japan (World?) (unknown revision, prototype?)
 tnzsop                          // B53?(c) 1988 Taito Corporation Japan (World?) (old pcb, prototype)
 
 @source:toaplan1.cpp
@@ -35794,6 +35841,7 @@ outzonecv                       // TP-O18 (c) 1990 Toaplan (TP-015 conversion)
 rallybik                        // B45 / TP-O12 (c) 1988 Taito
 samesame                        // TP-O17 (c) 1989 Toaplan
 samesame2                       // TP-O17 (c) 1989 Toaplan
+samesamenh                      // hack
 truxton                         // B65 / TP-O13B (c) 1988 Taito
 vimana                          // TP-O19 (c) 1991 Toaplan (+ Tecmo license when set to Japan)
 vimanaj                         // TP-O19 (c) 1991 Toaplan (+ Tecmo license when set to Japan)
@@ -35907,6 +35955,9 @@ topspeedu                       // B14 (c) 1987 Taito America Corporation (US)
 toratora                        // (c) 1980 Game Plan
 toratorab                       // (c) 1980 Game Plan
 
+ at source:tosh1000.cpp
+tosh1000
+
 @source:tourtabl.cpp
 tourtab2                        // 030170           1978/03 [6507]
 tourtabl                        // 030170           1978/03 [6507]
@@ -37024,6 +37075,7 @@ id4f_201                        //
 jplstw20                        //
 jplstw22                        //
 lostspc                         //
+lostspcf                        //
 lostspcg                        //
 lostspc_d1                      //
 mononew                         //
@@ -37161,6 +37213,7 @@ wackadoo                        //
 xfiles2                         //
 xfiles20                        //
 xfilesp                         //
+xfilespf                        //
 
 @source:wicat.cpp
 wicat                           //
@@ -37944,6 +37997,9 @@ zrt80                           //
 @source:zsbc3.cpp
 zsbc3                           //
 
+ at source:zwackery.cpp
+zwackery                        // (c) 1984
+
 @source:zx.cpp
 lambda                          // Lambda 8300
 pc8300                          // Your Computer - PC8300
diff --git a/src/mame/mess.flt b/src/mame/mess.flt
index 4292de4..e701eea 100644
--- a/src/mame/mess.flt
+++ b/src/mame/mess.flt
@@ -309,6 +309,7 @@ lisa.cpp
 llc.cpp
 lola8a.cpp
 lviv.cpp
+lwriter.cpp
 lynx.cpp
 m20.cpp
 m24.cpp
@@ -318,6 +319,7 @@ m79152pc.cpp
 mac.cpp
 mac128.cpp
 macpci.cpp
+magnum.cpp
 mbc200.cpp
 mbc55x.cpp
 mbee.cpp
@@ -623,6 +625,7 @@ tm990189.cpp
 tmc1800.cpp
 tmc2000e.cpp
 tmc600.cpp
+tosh1000.cpp
 tr606.cpp
 tranz330.cpp
 tricep.cpp
diff --git a/src/mame/nl.lst b/src/mame/nl.lst
index 44f009e..ddd0639 100644
--- a/src/mame/nl.lst
+++ b/src/mame/nl.lst
@@ -60,3 +60,5 @@ spelunkr                        // (c) 1985 licensed from Broderbund
 spelunkrj                       // (c) 1985 licensed from Broderbund
 yanchamr                        // (c) 1986 (Japan)
 youjyudn                        // (c) 1986 (Japan)
+
+hazl1500
diff --git a/src/mame/video/4enraya.cpp b/src/mame/video/4enraya.cpp
index ca22f8c..d4cbe45 100644
--- a/src/mame/video/4enraya.cpp
+++ b/src/mame/video/4enraya.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina, Roberto Fresca
 /***************************************************************************
 
diff --git a/src/mame/video/beezer.cpp b/src/mame/video/beezer.cpp
deleted file mode 100644
index c957e1d..0000000
--- a/src/mame/video/beezer.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Mathis Rosenhauer
-#include "emu.h"
-#include "cpu/m6809/m6809.h"
-#include "machine/6522via.h"
-#include "includes/beezer.h"
-
-
-TIMER_DEVICE_CALLBACK_MEMBER(beezer_state::beezer_interrupt)
-{
-	int scanline = param;
-	via6522_device *via_0 = machine().device<via6522_device>("via6522_0");
-
-	via_0->write_ca2((scanline & 0x20) ? 1 : 0);
-	#if 0
-	if (scanline == 240) // actually unused by the game! (points to a tight loop)
-		m_maincpu->set_input_line(M6809_FIRQ_LINE, ASSERT_LINE);
-	else
-		m_maincpu->set_input_line(M6809_FIRQ_LINE, CLEAR_LINE);
-	#endif
-}
-
-uint32_t beezer_state::screen_update_beezer(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
-{
-	uint8_t *videoram = m_videoram;
-	int x,y;
-
-	for (y = cliprect.min_y; y <= cliprect.max_y; y++)
-		for (x = cliprect.min_x; x <= cliprect.max_x; x+=2)
-		{
-			bitmap.pix16(y, x+1) = videoram[0x80*x+y] & 0x0f;
-			bitmap.pix16(y, x+0) = videoram[0x80*x+y] >> 4;
-		}
-
-	return 0;
-}
-
-WRITE8_MEMBER(beezer_state::beezer_map_w)
-{
-	/*
-	  bit 7 -- 330  ohm resistor  -- BLUE
-	        -- 560  ohm resistor  -- BLUE
-	        -- 330  ohm resistor  -- GREEN
-	        -- 560  ohm resistor  -- GREEN
-	        -- 1.2 kohm resistor  -- GREEN
-	        -- 330  ohm resistor  -- RED
-	        -- 560  ohm resistor  -- RED
-	  bit 0 -- 1.2 kohm resistor  -- RED
-	*/
-
-	int r, g, b, bit0, bit1, bit2;
-
-	/* red component */
-	bit0 = (data >> 0) & 0x01;
-	bit1 = (data >> 1) & 0x01;
-	bit2 = (data >> 2) & 0x01;
-	r = 0x26 * bit0 + 0x50 * bit1 + 0x89 * bit2;
-	/* green component */
-	bit0 = (data >> 3) & 0x01;
-	bit1 = (data >> 4) & 0x01;
-	bit2 = (data >> 5) & 0x01;
-	g = 0x26 * bit0 + 0x50 * bit1 + 0x89 * bit2;
-	/* blue component */
-	bit0 = (data >> 6) & 0x01;
-	bit1 = (data >> 7) & 0x01;
-	b = 0x5f * bit0 + 0xa0 * bit1;
-
-	m_palette->set_pen_color(offset, rgb_t(r, g, b));
-}
-
-READ8_MEMBER(beezer_state::beezer_line_r)
-{
-	return m_screen->vpos();
-//  Note: was (m_scanline & 0xfe) << 1; with scanline % 128
-}
diff --git a/src/mame/video/eolith.cpp b/src/mame/video/eolith.cpp
index 5429991..306766a 100644
--- a/src/mame/video/eolith.cpp
+++ b/src/mame/video/eolith.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina,Pierpaolo Prazzoli
 #include "emu.h"
 #include "includes/eolith.h"
diff --git a/src/mame/video/fcombat.cpp b/src/mame/video/fcombat.cpp
index 086db4a..80f0e67 100644
--- a/src/mame/video/fcombat.cpp
+++ b/src/mame/video/fcombat.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /***************************************************************************
 
diff --git a/src/mame/video/finalizr.cpp b/src/mame/video/finalizr.cpp
index dfff8a3..716c038 100644
--- a/src/mame/video/finalizr.cpp
+++ b/src/mame/video/finalizr.cpp
@@ -217,9 +217,17 @@ uint32_t finalizr_state::screen_update_finalizr(screen_device &screen, bitmap_in
 	const rectangle &visarea = screen.visible_area();
 	rectangle clip = cliprect;
 
-	clip.min_x = visarea.min_x;
-	clip.max_x = visarea.min_x + 31;
-	m_fg_tilemap->set_scrolldx(0,-32);
+	if (flip_screen())
+	{
+		clip.min_x = visarea.max_x - 31;
+		clip.max_x = visarea.max_x;
+	}
+	else
+	{
+		clip.min_x = visarea.min_x;
+		clip.max_x = visarea.min_x + 31;
+	}
+
 	m_fg_tilemap->draw(screen, bitmap, clip, 0, 0);
 
 	return 0;
diff --git a/src/mame/video/freekick.cpp b/src/mame/video/freekick.cpp
index 0feab9e..a02f006 100644
--- a/src/mame/video/freekick.cpp
+++ b/src/mame/video/freekick.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina,David Haywood
 /* Free Kick Video Hardware */
 
diff --git a/src/mame/video/fromance.cpp b/src/mame/video/fromance.cpp
index a8ec021..a42eb22 100644
--- a/src/mame/video/fromance.cpp
+++ b/src/mame/video/fromance.cpp
@@ -217,6 +217,7 @@ WRITE8_MEMBER(fromance_state::fromance_scroll_w)
 	}
 	else
 	{
+
 		switch (offset)
 		{
 			case 0:
@@ -250,6 +251,33 @@ TIMER_CALLBACK_MEMBER(fromance_state::crtc_interrupt_gen)
 		m_crtc_timer->adjust(m_screen->frame_period() / param, 0, m_screen->frame_period() / param);
 }
 
+/*
+ 0  1  2  3  4  5
+57 63 69 71 1f 00 (all games)
+4f 62 69 71 1f 04 nekkyoku
+ 8  9  A  B
+7a 7b 7d 7f  (all games)
+79 7a 7d 7f  nekkyoku (gameplay/title screen)
+77 79 7d 7e  nekkyoku (gals display)
+ */
+// TODO: guesswork, looks fully programmable
+void fromance_state::crtc_refresh()
+{
+	if(m_crtc_data[0] == 0) // sanity check
+		return;
+
+	rectangle visarea;
+	attoseconds_t refresh;
+
+	visarea.min_x = 0;
+	visarea.min_y = 0;
+	visarea.max_x = ((m_crtc_data[0]+1)*4) - 1;
+	visarea.max_y = 240 - 1;
+
+	refresh = HZ_TO_ATTOSECONDS(60);
+
+	m_screen->configure(512, 256, visarea, refresh);
+}
 
 WRITE8_MEMBER(fromance_state::fromance_crtc_data_w)
 {
@@ -257,8 +285,12 @@ WRITE8_MEMBER(fromance_state::fromance_crtc_data_w)
 
 	switch (m_crtc_register)
 	{
-		/* only register we know about.... */
+		case 0x00:
+			crtc_refresh();
+			break;
+
 		case 0x0b:
+			// TODO: actually is never > 0x80?
 			m_crtc_timer->adjust(m_screen->time_until_vblank_start(), (data > 0x80) ? 2 : 1);
 			break;
 
@@ -271,13 +303,10 @@ WRITE8_MEMBER(fromance_state::fromance_crtc_data_w)
 
 WRITE8_MEMBER(fromance_state::fromance_crtc_register_w)
 {
-	m_crtc_register = data;
+	m_crtc_register = data & 0x0f;
 }
 
 
-
-
-
 /*************************************
  *
  *  Main screen refresh
diff --git a/src/mame/video/homerun.cpp b/src/mame/video/homerun.cpp
index 7a814a7..3bb2660 100644
--- a/src/mame/video/homerun.cpp
+++ b/src/mame/video/homerun.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /*************************************************************************
 
diff --git a/src/mame/video/k053246_k053247_k055673.cpp b/src/mame/video/k053246_k053247_k055673.cpp
index 714e581..30b0a5c 100644
--- a/src/mame/video/k053246_k053247_k055673.cpp
+++ b/src/mame/video/k053246_k053247_k055673.cpp
@@ -1023,10 +1023,10 @@ void k055673_device::device_start()
 	memset(m_kx46_regs, 0, 8);
 	memset(m_kx47_regs, 0, 32);
 
-	machine().save().save_pointer(NAME(m_ram.get()), 0x800);
-	machine().save().save_item(NAME(m_kx46_regs));
-	machine().save().save_item(NAME(m_kx47_regs));
-	machine().save().save_item(NAME(m_objcha_line));
+	save_pointer(NAME(m_ram.get()), 0x800);
+	save_item(NAME(m_kx46_regs));
+	save_item(NAME(m_kx47_regs));
+	save_item(NAME(m_objcha_line));
 }
 
 //-------------------------------------------------
diff --git a/src/mame/video/k054156_k054157_k056832.cpp b/src/mame/video/k054156_k054157_k056832.cpp
index 51502c1..b11001a 100644
--- a/src/mame/video/k054156_k054157_k056832.cpp
+++ b/src/mame/video/k054156_k054157_k056832.cpp
@@ -291,8 +291,6 @@ void k056832_device::create_tilemaps()
 
 void k056832_device::finalize_init()
 {
-	int i;
-
 	update_page_layout();
 
 	change_rambank();
@@ -301,37 +299,33 @@ void k056832_device::finalize_init()
 	save_item(NAME(m_videoram));
 	save_item(NAME(m_regs));
 	save_item(NAME(m_regsb));
+
+	save_item(NAME(m_cur_gfx_banks));
+
+	save_item(NAME(m_rom_half));
+
+	save_item(NAME(m_layer_assoc_with_page));
+	save_item(NAME(m_layer_offs));
+	save_item(NAME(m_lsram_page));
 	save_item(NAME(m_x));
 	save_item(NAME(m_y));
 	save_item(NAME(m_w));
 	save_item(NAME(m_h));
 	save_item(NAME(m_dx));
 	save_item(NAME(m_dy));
+	save_item(NAME(m_line_dirty));
+	save_item(NAME(m_all_lines_dirty));
+	save_item(NAME(m_page_tile_mode));
+	save_item(NAME(m_last_colorbase));
 	save_item(NAME(m_layer_tile_mode));
-
 	save_item(NAME(m_default_layer_association));
+	save_item(NAME(m_layer_association));
 	save_item(NAME(m_active_layer));
 	save_item(NAME(m_linemap_enabled));
 	save_item(NAME(m_use_ext_linescroll));
 	save_item(NAME(m_uses_tile_banks));
 	save_item(NAME(m_cur_tile_bank));
-	save_item(NAME(m_rom_half));
-	save_item(NAME(m_all_lines_dirty));
-	save_item(NAME(m_page_tile_mode));
 
-	for (i = 0; i < 8; i++)
-	{
-		save_item(NAME(m_layer_offs[i]), i);
-		save_item(NAME(m_lsram_page[i]), i);
-	}
-
-	for (i = 0; i < K056832_PAGE_COUNT; i++)
-	{
-		save_item(NAME(m_line_dirty[i]), i);
-		save_item(NAME(m_all_lines_dirty[i]), i);
-		save_item(NAME(m_page_tile_mode[i]), i);
-		save_item(NAME(m_last_colorbase[i]), i);
-	}
 
 	machine().save().register_postload(save_prepost_delegate(FUNC(k056832_device::postload), this));
 }
diff --git a/src/mame/video/konamigx.cpp b/src/mame/video/konamigx.cpp
index c637dfd..205a0c1 100644
--- a/src/mame/video/konamigx.cpp
+++ b/src/mame/video/konamigx.cpp
@@ -1097,7 +1097,20 @@ void konamigx_state::common_init()
 		m_gx_tilebanks[i] = m_gx_oldbanks[i] = 0;
 	}
 
-	machine().save().save_item(NAME(m_gx_tilebanks));
+	save_pointer(NAME(m_gx_spriteram), 0x800);
+	save_item(NAME(m_gx_tilebanks));
+	save_item(NAME(m_k053247_vrcbk));
+	save_item(NAME(m_k053247_coreg));
+	save_item(NAME(m_k053247_coregshift));
+	save_item(NAME(m_k053247_opset));
+	save_item(NAME(m_opri));
+	save_item(NAME(m_oinprion));
+	save_item(NAME(m_vcblk));
+	save_item(NAME(m_ocblk));
+	save_item(NAME(m_vinmix));
+	save_item(NAME(m_vmixon));
+	save_item(NAME(m_osinmix));
+	save_item(NAME(m_osmixon));
 
 	m_gx_tilemode = 0;
 
diff --git a/src/mame/video/ksayakyu.cpp b/src/mame/video/ksayakyu.cpp
index d266bf4..0894ca2 100644
--- a/src/mame/video/ksayakyu.cpp
+++ b/src/mame/video/ksayakyu.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 #include "emu.h"
 #include "includes/ksayakyu.h"
diff --git a/src/mame/video/ladyfrog.cpp b/src/mame/video/ladyfrog.cpp
index 77c5bd0..cbaaf56 100644
--- a/src/mame/video/ladyfrog.cpp
+++ b/src/mame/video/ladyfrog.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /***************************************************************************
 
diff --git a/src/mame/video/leland.cpp b/src/mame/video/leland.cpp
index 8f110ba..7f51b56 100644
--- a/src/mame/video/leland.cpp
+++ b/src/mame/video/leland.cpp
@@ -63,6 +63,18 @@ VIDEO_START_MEMBER(leland_state,leland)
 	/* scanline timer */
 	m_scanline_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(leland_state::scanline_callback),this));
 	m_scanline_timer->adjust(m_screen->time_until_pos(0));
+
+	save_item(NAME(m_gfx_control));
+	save_pointer(NAME(m_video_ram.get()), VRAM_SIZE);
+	save_item(NAME(m_xscroll));
+	save_item(NAME(m_yscroll));
+	save_item(NAME(m_gfxbank));
+	save_item(NAME(m_last_scanline));
+	for (uint8_t i = 0; i < 2; i++)
+	{
+		save_item(NAME(m_vram_state[i].m_addr), i);
+		save_item(NAME(m_vram_state[i].m_latch), i);
+	}
 }
 
 VIDEO_START_MEMBER(leland_state,ataxx)
@@ -72,6 +84,16 @@ VIDEO_START_MEMBER(leland_state,ataxx)
 
 	/* allocate memory */
 	m_ataxx_qram = make_unique_clear<uint8_t[]>(QRAM_SIZE);
+
+	save_pointer(NAME(m_video_ram.get()), VRAM_SIZE);
+	save_pointer(NAME(m_ataxx_qram.get()), QRAM_SIZE);
+	save_item(NAME(m_xscroll));
+	save_item(NAME(m_yscroll));
+	for (uint8_t i = 0; i < 2; i++)
+	{
+		save_item(NAME(m_vram_state[i].m_addr), i);
+		save_item(NAME(m_vram_state[i].m_latch), i);
+	}
 }
 
 
diff --git a/src/mame/video/m58.cpp b/src/mame/video/m58.cpp
index 1e0d28e..352f57c 100644
--- a/src/mame/video/m58.cpp
+++ b/src/mame/video/m58.cpp
@@ -127,6 +127,7 @@ WRITE8_MEMBER(m58_state::scroll_panel_w)
 		col = ((col >> 3) | col) & 3;
 
 		m_scroll_panel_bitmap.pix16(sy, sx + i) = 0x100 + (sy & 0xfc) + col;
+		m_scroll_panel_bitmap.pix16(sy, sx + i + 0x2c8) = 0x100 + (sy & 0xfc) + col; // for flipscreen
 	}
 }
 
@@ -169,13 +170,8 @@ TILEMAP_MAPPER_MEMBER(m58_state::tilemap_scan_rows)
 
 void m58_state::video_start()
 {
-	int width = m_screen->width();
-	int height = m_screen->height();
-	const rectangle &visarea = m_screen->visible_area();
-
 	m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(m58_state::get_bg_tile_info),this), tilemap_mapper_delegate(FUNC(m58_state::tilemap_scan_rows),this), 8, 8, 64, 32);
-	m_bg_tilemap->set_scrolldx(visarea.min_x, width - (visarea.max_x + 1));
-	m_bg_tilemap->set_scrolldy(visarea.min_y - 8, height + 16 - (visarea.max_y + 1));
+	m_bg_tilemap->set_scrolldy(32, 32);
 
 	m_screen->register_screen_bitmap(m_scroll_panel_bitmap);
 	save_item(NAME(m_scroll_panel_bitmap));
@@ -192,7 +188,7 @@ void m58_state::video_start()
 WRITE8_MEMBER(m58_state::flipscreen_w)
 {
 	/* screen flip is handled both by software and hardware */
-	flip_screen_set((data & 0x01) ^ (~ioport("DSW2")->read() & 0x01));
+	flip_screen_set(BIT(data, 0) ^ BIT(~ioport("DSW2")->read(), 0));
 
 	machine().bookkeeping().coin_counter_w(0, data & 0x02);
 	machine().bookkeeping().coin_counter_w(1, data & 0x20);
diff --git a/src/mame/video/mcr68.cpp b/src/mame/video/mcr68.cpp
index 30de029..10479d1 100644
--- a/src/mame/video/mcr68.cpp
+++ b/src/mame/video/mcr68.cpp
@@ -31,25 +31,6 @@ TILE_GET_INFO_MEMBER(mcr68_state::get_bg_tile_info)
 }
 
 
-TILE_GET_INFO_MEMBER(mcr68_state::zwackery_get_bg_tile_info)
-{
-	uint16_t *videoram = m_videoram;
-	int data = videoram[tile_index];
-	int color = (data >> 13) & 7;
-	SET_TILE_INFO_MEMBER(0, data & 0x3ff, color, TILE_FLIPYX(data >> 11));
-}
-
-
-TILE_GET_INFO_MEMBER(mcr68_state::zwackery_get_fg_tile_info)
-{
-	uint16_t *videoram = m_videoram;
-	int data = videoram[tile_index];
-	int color = (data >> 13) & 7;
-	SET_TILE_INFO_MEMBER(2, data & 0x3ff, color, TILE_FLIPYX(data >> 11));
-	tileinfo.category = (color != 0);
-}
-
-
 
 /*************************************
  *
@@ -65,70 +46,6 @@ VIDEO_START_MEMBER(mcr68_state,mcr68)
 }
 
 
-VIDEO_START_MEMBER(mcr68_state,zwackery)
-{
-	const uint8_t *colordatabase = (const uint8_t *)memregion("gfx3")->base();
-	gfx_element *gfx0 = m_gfxdecode->gfx(0);
-	gfx_element *gfx2 = m_gfxdecode->gfx(2);
-	uint8_t *dest0;
-	uint8_t *dest2;
-	int code, y, x;
-
-	/* initialize the background tilemap */
-	m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(mcr68_state::zwackery_get_bg_tile_info),this), TILEMAP_SCAN_ROWS,  16,16, 32,32);
-
-	/* initialize the foreground tilemap */
-	m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(mcr68_state::zwackery_get_fg_tile_info),this), TILEMAP_SCAN_ROWS,  16,16, 32,32);
-	m_fg_tilemap->set_transparent_pen(0);
-
-	/* allocate memory for the assembled gfx data */
-	m_srcdata0 = std::make_unique<uint8_t[]>(gfx0->elements() * gfx0->width() * gfx0->height());
-	m_srcdata2 = std::make_unique<uint8_t[]>(gfx2->elements() * gfx2->width() * gfx2->height());
-
-	/* "colorize" each code */
-	dest0 = m_srcdata0.get();
-	dest2 = m_srcdata2.get();
-	for (code = 0; code < gfx0->elements(); code++)
-	{
-		const uint8_t *coldata = colordatabase + code * 32;
-		const uint8_t *gfxdata0 = gfx0->get_data(code);
-		const uint8_t *gfxdata2 = gfx2->get_data(code);
-
-		/* assume 16 rows */
-		for (y = 0; y < 16; y++)
-		{
-			const uint8_t *gd0 = gfxdata0;
-			const uint8_t *gd2 = gfxdata2;
-
-			/* 16 columns */
-			for (x = 0; x < 16; x++, gd0++, gd2++)
-			{
-				int coloffs = (y & 0x0c) | ((x >> 2) & 0x03);
-				int pen0 = coldata[coloffs * 2 + 0];
-				int pen1 = coldata[coloffs * 2 + 1];
-				int tp0, tp1;
-
-				/* every 4 pixels gets its own foreground/background colors */
-				*dest0++ = *gd0 ? pen1 : pen0;
-
-				/* for gfx 2, we convert all low-priority pens to 0 */
-				tp0 = (pen0 & 0x80) ? pen0 : 0;
-				tp1 = (pen1 & 0x80) ? pen1 : 0;
-				*dest2++ = *gd2 ? tp1 : tp0;
-			}
-
-			/* advance */
-			gfxdata0 += gfx0->rowbytes();
-			gfxdata2 += gfx2->rowbytes();
-		}
-	}
-
-	/* make the assembled data our new source data */
-	gfx0->set_raw_layout(m_srcdata0.get(), gfx0->width(), gfx0->height(), gfx0->elements(), 8 * gfx0->width(), 8 * gfx0->width() * gfx0->height());
-	gfx2->set_raw_layout(m_srcdata2.get(), gfx2->width(), gfx2->height(), gfx2->elements(), 8 * gfx2->width(), 8 * gfx2->width() * gfx2->height());
-}
-
-
 
 /*************************************
  *
@@ -144,24 +61,6 @@ WRITE16_MEMBER(mcr68_state::mcr68_videoram_w)
 }
 
 
-WRITE16_MEMBER(mcr68_state::zwackery_videoram_w)
-{
-	uint16_t *videoram = m_videoram;
-	COMBINE_DATA(&videoram[offset]);
-	m_bg_tilemap->mark_tile_dirty(offset);
-	m_fg_tilemap->mark_tile_dirty(offset);
-}
-
-
-WRITE16_MEMBER(mcr68_state::zwackery_spriteram_w)
-{
-	/* yech -- Zwackery relies on the upper 8 bits of a spriteram read being $ff! */
-	/* to make this happen we always write $ff in the upper 8 bits */
-	COMBINE_DATA(&m_spriteram[offset]);
-	m_spriteram[offset] |= 0xff00;
-}
-
-
 
 /*************************************
  *
@@ -222,63 +121,6 @@ void mcr68_state::mcr68_update_sprites(screen_device &screen, bitmap_ind16 &bitm
 }
 
 
-void mcr68_state::zwackery_update_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int priority)
-{
-	uint16_t *spriteram = m_spriteram;
-	int offs;
-
-	screen.priority().fill(1, cliprect);
-
-	/* loop over sprite RAM */
-	for (offs = m_spriteram.bytes() / 2 - 4;offs >= 0;offs -= 4)
-	{
-		int code, color, flipx, flipy, x, y, flags;
-
-		/* get the code and skip if zero */
-		code = LOW_BYTE(spriteram[offs + 2]);
-		if (code == 0)
-			continue;
-
-		/* extract the flag bits and determine the color */
-		flags = LOW_BYTE(spriteram[offs + 1]);
-		color = ((~flags >> 2) & 0x0f) | ((flags & 0x02) << 3);
-
-		/* for low priority, draw everything but color 7 */
-		if (!priority)
-		{
-			if (color == 7)
-				continue;
-		}
-
-		/* for high priority, only draw color 7 */
-		else
-		{
-			if (color != 7)
-				continue;
-		}
-
-		/* determine flipping and coordinates */
-		flipx = ~flags & 0x40;
-		flipy = flags & 0x80;
-		x = (231 - LOW_BYTE(spriteram[offs + 3])) * 2;
-		y = (241 - LOW_BYTE(spriteram[offs])) * 2;
-
-		if (x <= -32) x += 512;
-
-		/* sprites use color 0 for background pen and 8 for the 'under tile' pen.
-		    The color 8 is used to cover over other sprites. */
-
-		/* first draw the sprite, visible */
-		m_gfxdecode->gfx(1)->prio_transmask(bitmap,cliprect, code, color, flipx, flipy, x, y,
-				screen.priority(), 0x00, 0x0101);
-
-		/* then draw the mask, behind the background but obscuring following sprites */
-		m_gfxdecode->gfx(1)->prio_transmask(bitmap,cliprect, code, color, flipx, flipy, x, y,
-				screen.priority(), 0x02, 0xfeff);
-	}
-}
-
-
 
 /*************************************
  *
@@ -301,20 +143,3 @@ uint32_t mcr68_state::screen_update_mcr68(screen_device &screen, bitmap_ind16 &b
 	mcr68_update_sprites(screen, bitmap, cliprect, 1);
 	return 0;
 }
-
-
-uint32_t mcr68_state::screen_update_zwackery(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
-{
-	/* draw the background */
-	m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
-
-	/* draw the low-priority sprites */
-	zwackery_update_sprites(screen, bitmap, cliprect, 0);
-
-	/* redraw tiles with priority over sprites */
-	m_fg_tilemap->draw(screen, bitmap, cliprect, 1, 0);
-
-	/* draw the high-priority sprites */
-	zwackery_update_sprites(screen, bitmap, cliprect, 1);
-	return 0;
-}
diff --git a/src/mame/video/mustache.cpp b/src/mame/video/mustache.cpp
index ca720e3..8e11878 100644
--- a/src/mame/video/mustache.cpp
+++ b/src/mame/video/mustache.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /***************************************************************************
 
@@ -54,14 +54,12 @@ WRITE8_MEMBER(mustache_state::videoram_w)
 
 WRITE8_MEMBER(mustache_state::video_control_w)
 {
-	if (flip_screen() != (data & 0x01))
-	{
-		flip_screen_set(data & 0x01);
-		machine().tilemap().mark_all_dirty();
-	}
+	/* It is assumed that screen flipping is controlled by both
+	   hardware (via a DIP switch, labeled "Hard SW" on the
+	   operator's sheet) and software, as in some Irem games */
+	flip_screen_set((data & 0x01) ^ BIT(~m_dswb->read(), 7));
 
 	/* tile bank */
-
 	if ((m_control_byte ^ data) & 0x08)
 	{
 		m_control_byte = data;
@@ -128,7 +126,7 @@ void mustache_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprec
 		if (flip_screen())
 		{
 			sx = 240 - sx;
-			sy = 240 - sy;
+			sy = 232 - sy;
 		}
 
 		gfx->transpen(bitmap,clip,
diff --git a/src/mame/video/nycaptor.cpp b/src/mame/video/nycaptor.cpp
index 22c82f9..56739d1 100644
--- a/src/mame/video/nycaptor.cpp
+++ b/src/mame/video/nycaptor.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /***************************************************************************
 
diff --git a/src/mame/video/phoenix.cpp b/src/mame/video/phoenix.cpp
index f4a8244..5c7b365 100644
--- a/src/mame/video/phoenix.cpp
+++ b/src/mame/video/phoenix.cpp
@@ -186,11 +186,6 @@ VIDEO_START_MEMBER(phoenix_state,phoenix)
 
 	m_fg_tilemap->set_transparent_pen(0);
 
-	m_fg_tilemap->set_scrolldx(0, (HTOTAL - HBSTART));
-	m_bg_tilemap->set_scrolldx(0, (HTOTAL - HBSTART));
-	m_fg_tilemap->set_scrolldy(0, (VTOTAL - VBSTART));
-	m_bg_tilemap->set_scrolldy(0, (VTOTAL - VBSTART));
-
 	save_pointer(NAME(m_videoram_pg[0].get()), 0x1000);
 	save_pointer(NAME(m_videoram_pg[1].get()), 0x1000);
 	save_item(NAME(m_videoram_pg_index));
@@ -233,7 +228,7 @@ WRITE8_MEMBER(phoenix_state::phoenix_videoram_w)
 			m_fg_tilemap->mark_tile_dirty(offset & 0x3ff);
 	}
 
-	/* as part of the protecion, Survival executes code from $43a4 */
+	/* as part of the protection, Survival executes code from $43a4 */
 	rom[offset + 0x4000] = data;
 }
 
@@ -360,7 +355,12 @@ CUSTOM_INPUT_MEMBER(phoenix_state::pleiads_protection_r)
 #define REMAP_JS(js) ((ret & 0xf) | ( (js & 0xf)  << 4))
 READ8_MEMBER(phoenix_state::survival_input_port_0_r)
 {
-	uint8_t ret = ~ioport("IN0")->read();
+	uint8_t ret;
+
+	if (m_cocktail_mode)
+		ret = ~ioport("IN1")->read();
+	else
+		ret = ~ioport("IN0")->read();
 
 	if( m_survival_input_readc++ == 2 )
 	{
diff --git a/src/mame/video/pitnrun.cpp b/src/mame/video/pitnrun.cpp
index 54d0036..86a9b8c 100644
--- a/src/mame/video/pitnrun.cpp
+++ b/src/mame/video/pitnrun.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina, Pierpaolo Prazzoli
 /***************************************************************************
 
diff --git a/src/mame/video/pk8000.cpp b/src/mame/video/pk8000.cpp
index e247913..291242e 100644
--- a/src/mame/video/pk8000.cpp
+++ b/src/mame/video/pk8000.cpp
@@ -3,64 +3,64 @@
 #include "emu.h"
 #include "includes/pk8000.h"
 
-READ8_MEMBER(pk8000_base_state::pk8000_video_color_r)
+READ8_MEMBER(pk8000_base_state::video_color_r)
 {
-	return m_pk8000_video_color;
+	return m_video_color;
 }
 
-WRITE8_MEMBER(pk8000_base_state::pk8000_video_color_w)
+WRITE8_MEMBER(pk8000_base_state::video_color_w)
 {
-	m_pk8000_video_color = data;
+	m_video_color = data;
 }
 
-READ8_MEMBER(pk8000_base_state::pk8000_text_start_r)
+READ8_MEMBER(pk8000_base_state::text_start_r)
 {
-	return m_pk8000_text_start;
+	return m_text_start;
 }
 
-WRITE8_MEMBER(pk8000_base_state::pk8000_text_start_w)
+WRITE8_MEMBER(pk8000_base_state::text_start_w)
 {
-	m_pk8000_text_start = data;
+	m_text_start = data;
 }
 
-READ8_MEMBER(pk8000_base_state::pk8000_chargen_start_r)
+READ8_MEMBER(pk8000_base_state::chargen_start_r)
 {
-	return m_pk8000_chargen_start;
+	return m_chargen_start;
 }
 
-WRITE8_MEMBER(pk8000_base_state::pk8000_chargen_start_w)
+WRITE8_MEMBER(pk8000_base_state::chargen_start_w)
 {
-	m_pk8000_chargen_start = data;
+	m_chargen_start = data;
 }
 
-READ8_MEMBER(pk8000_base_state::pk8000_video_start_r)
+READ8_MEMBER(pk8000_base_state::video_start_r)
 {
-	return m_pk8000_video_start;
+	return m_video_start;
 }
 
-WRITE8_MEMBER(pk8000_base_state::pk8000_video_start_w)
+WRITE8_MEMBER(pk8000_base_state::video_start_w)
 {
-	m_pk8000_video_start = data;
+	m_video_start = data;
 }
 
-READ8_MEMBER(pk8000_base_state::pk8000_color_start_r)
+READ8_MEMBER(pk8000_base_state::color_start_r)
 {
-	return m_pk8000_color_start;
+	return m_color_start;
 }
 
-WRITE8_MEMBER(pk8000_base_state::pk8000_color_start_w)
+WRITE8_MEMBER(pk8000_base_state::color_start_w)
 {
-	m_pk8000_color_start = data;
+	m_color_start = data;
 }
 
-READ8_MEMBER(pk8000_base_state::pk8000_color_r)
+READ8_MEMBER(pk8000_base_state::color_r)
 {
-	return m_pk8000_color[offset];
+	return m_color[offset];
 }
 
-WRITE8_MEMBER(pk8000_base_state::pk8000_color_w)
+WRITE8_MEMBER(pk8000_base_state::color_w)
 {
-	m_pk8000_color[offset] = data;
+	m_color[offset] = data;
 }
 
 static const rgb_t pk8000_palette[16] = {
@@ -87,43 +87,43 @@ PALETTE_INIT_MEMBER(pk8000_base_state, pk8000)
 	palette.set_pen_colors(0, pk8000_palette, ARRAY_LENGTH(pk8000_palette));
 }
 
-READ8_MEMBER(pk8000_base_state::pk8000_84_porta_r)
+READ8_MEMBER(pk8000_base_state::_84_porta_r)
 {
-	return m_pk8000_video_mode;
+	return m_video_mode;
 }
 
-WRITE8_MEMBER(pk8000_base_state::pk8000_84_porta_w)
+WRITE8_MEMBER(pk8000_base_state::_84_porta_w)
 {
-	m_pk8000_video_mode = data;
+	m_video_mode = data;
 }
 
-WRITE8_MEMBER(pk8000_base_state::pk8000_84_portc_w)
+WRITE8_MEMBER(pk8000_base_state::_84_portc_w)
 {
-	m_pk8000_video_enable = BIT(data,4);
+	m_video_enable = BIT(data,4);
 }
 
-uint32_t pk8000_base_state::pk8000_video_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, uint8_t *videomem)
+uint32_t pk8000_base_state::video_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, uint8_t *videomem)
 {
 	int x,y,j,b;
-	uint16_t offset = (m_pk8000_video_mode & 0xc0) << 8;
+	uint16_t offset = (m_video_mode & 0xc0) << 8;
 	rectangle my_rect;
 	my_rect.set(0, 256+32-1, 0, 192+32-1);
 
-	if (m_pk8000_video_enable) {
-		bitmap.fill((m_pk8000_video_color >> 4) & 0x0f, my_rect);
+	if (m_video_enable) {
+		bitmap.fill((m_video_color >> 4) & 0x0f, my_rect);
 
-		if (BIT(m_pk8000_video_mode,4)==0){
+		if (BIT(m_video_mode,4)==0){
 			// Text mode
-			if (BIT(m_pk8000_video_mode,5)==0){
+			if (BIT(m_video_mode,5)==0){
 				// 32 columns
 				for (y = 0; y < 24; y++)
 				{
 					for (x = 0; x < 32; x++)
 					{
-						uint8_t chr  = videomem[x +(y*32) + ((m_pk8000_text_start & 0x0f) << 10)+offset] ;
-						uint8_t color= m_pk8000_color[chr>>3];
+						uint8_t chr  = videomem[x +(y*32) + ((m_text_start & 0x0f) << 10)+offset] ;
+						uint8_t color= m_color[chr>>3];
 						for (j = 0; j < 8; j++) {
-							uint8_t code = videomem[((chr<<3) + j) + ((m_pk8000_chargen_start & 0x0e) << 10)+offset];
+							uint8_t code = videomem[((chr<<3) + j) + ((m_chargen_start & 0x0e) << 10)+offset];
 
 							for (b = 0; b < 8; b++)
 							{
@@ -139,12 +139,12 @@ uint32_t pk8000_base_state::pk8000_video_update(screen_device &screen, bitmap_in
 				{
 					for (x = 0; x < 42; x++)
 					{
-						uint8_t chr = videomem[x +(y*64) + ((m_pk8000_text_start & 0x0e) << 10)+offset] ;
+						uint8_t chr = videomem[x +(y*64) + ((m_text_start & 0x0e) << 10)+offset] ;
 						for (j = 0; j < 8; j++) {
-							uint8_t code = videomem[((chr<<3) + j) + ((m_pk8000_chargen_start  & 0x0e) << 10)+offset];
+							uint8_t code = videomem[((chr<<3) + j) + ((m_chargen_start  & 0x0e) << 10)+offset];
 							for (b = 2; b < 8; b++)
 							{
-								uint8_t col = ((code >> b) & 0x01) ? (m_pk8000_video_color) & 0x0f : (m_pk8000_video_color>>4) & 0x0f;
+								uint8_t col = ((code >> b) & 0x01) ? (m_video_color) & 0x0f : (m_video_color>>4) & 0x0f;
 								bitmap.pix16((y*8)+j+16, x*6+(7-b)+16+8) =  col;
 							}
 						}
@@ -155,11 +155,11 @@ uint32_t pk8000_base_state::pk8000_video_update(screen_device &screen, bitmap_in
 			//Graphics
 			for (y = 0; y < 24; y++)
 			{
-				uint16_t off_color = (((~m_pk8000_color_start) & 0x08) << 10)+offset + ((y>>3)<<11);
-				uint16_t off_code  = (((~m_pk8000_video_start) & 0x08) << 10)+offset + ((y>>3)<<11);
+				uint16_t off_color = (((~m_color_start) & 0x08) << 10)+offset + ((y>>3)<<11);
+				uint16_t off_code  = (((~m_video_start) & 0x08) << 10)+offset + ((y>>3)<<11);
 				for (x = 0; x < 32; x++)
 				{
-					uint8_t chr  = videomem[x +(y*32) + ((m_pk8000_chargen_start & 0x0e) << 10)+offset] ;
+					uint8_t chr  = videomem[x +(y*32) + ((m_chargen_start & 0x0e) << 10)+offset] ;
 					for (j = 0; j < 8; j++) {
 						uint8_t color= videomem[((chr<<3) + j)+off_color];
 						uint8_t code = videomem[((chr<<3) + j)+off_code];
diff --git a/src/mame/video/rltennis.cpp b/src/mame/video/rltennis.cpp
index c2e4302..0a3ada8 100644
--- a/src/mame/video/rltennis.cpp
+++ b/src/mame/video/rltennis.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /****************************************************************************************
  Reality Tennis - (c) 1993 TCH
diff --git a/src/mame/video/shootout.cpp b/src/mame/video/shootout.cpp
index ecc52ee..a8eaf92 100644
--- a/src/mame/video/shootout.cpp
+++ b/src/mame/video/shootout.cpp
@@ -83,7 +83,7 @@ void shootout_state::video_start()
 	m_foreground = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(shootout_state::get_fg_tile_info),this), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
 	m_foreground->set_transparent_pen(0 );
 
-	save_item(NAME(m_bFlicker));
+	save_item(NAME(m_ccnt_old_val));
 }
 
 void shootout_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int bank_bits )
@@ -92,7 +92,7 @@ void shootout_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, c
 	const uint8_t *source = m_spriteram+127*4;
 	int count;
 
-	m_bFlicker = !m_bFlicker;
+	bool m_bFlicker = (screen.frame_number () & 1) != 0;
 
 	for( count=0; count<128; count++ )
 	{
diff --git a/src/mame/video/sidepckt.cpp b/src/mame/video/sidepckt.cpp
index d694900..cafe257 100644
--- a/src/mame/video/sidepckt.cpp
+++ b/src/mame/video/sidepckt.cpp
@@ -15,9 +15,8 @@
 PALETTE_INIT_MEMBER(sidepckt_state, sidepckt)
 {
 	const uint8_t *color_prom = memregion("proms")->base();
-	int i;
 
-	for (i = 0;i < palette.entries();i++)
+	for (int i = 0;i < palette.entries();i++)
 	{
 		int bit0,bit1,bit2,bit3,r,g,b;
 
@@ -100,10 +99,19 @@ WRITE8_MEMBER(sidepckt_state::colorram_w)
 	m_bg_tilemap->mark_tile_dirty(offset);
 }
 
-WRITE8_MEMBER(sidepckt_state::flipscreen_w)
+READ8_MEMBER(sidepckt_state::scroll_y_r)
 {
-	int flipscreen = data;
-	machine().tilemap().set_flip_all(flipscreen ? TILEMAP_FLIPY : TILEMAP_FLIPX);
+	return (m_scroll_y);
+}
+
+WRITE8_MEMBER(sidepckt_state::scroll_y_w)
+{
+	// Bits 0-5: Scroll y
+	m_scroll_y = data & 0x3F;
+
+	// Other bits: Unknown, but they seem never written
+	if (data > 0x3F)
+		logerror ("scroll_y_w: Unknown write -> data = 0x%02X\n", data);
 }
 
 
@@ -117,22 +125,22 @@ void sidepckt_state::draw_sprites(bitmap_ind16 &bitmap,const rectangle &cliprect
 {
 	for (int offs = 0;offs < m_spriteram.bytes(); offs += 4)
 	{
-		int sx,sy,code,color,flipx,flipy;
+		int attr  = m_spriteram[offs | 1];
+		int code  = ((attr & 0x03) << 8) | m_spriteram[offs | 3];
+		int color = (attr & 0xf0) >> 4;
 
-		code = m_spriteram[offs+3] + ((m_spriteram[offs+1] & 0x03) << 8);
-		color = (m_spriteram[offs+1] & 0xf0) >> 4;
+		int sx = m_spriteram[offs | 2] - 2;
+		int sy = m_spriteram[offs];
 
-		sx = m_spriteram[offs+2]-2;
-		sy = m_spriteram[offs];
-
-		flipx = m_spriteram[offs+1] & 0x08;
-		flipy = m_spriteram[offs+1] & 0x04;
+		int flipx = attr & 0x08;
+		int flipy = attr & 0x04;
 
 		m_gfxdecode->gfx(1)->transpen(bitmap,cliprect,
 				code,
 				color,
 				flipx,flipy,
 				sx,sy,0);
+
 		/* wraparound */
 		m_gfxdecode->gfx(1)->transpen(bitmap,cliprect,
 				code,
@@ -145,6 +153,8 @@ void sidepckt_state::draw_sprites(bitmap_ind16 &bitmap,const rectangle &cliprect
 
 uint32_t sidepckt_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
 {
+	m_bg_tilemap->set_scrolly (0, m_scroll_y);
+
 	m_bg_tilemap->draw(screen, bitmap, cliprect, TILEMAP_DRAW_LAYER1,0);
 	draw_sprites(bitmap,cliprect);
 	m_bg_tilemap->draw(screen, bitmap, cliprect, TILEMAP_DRAW_LAYER0,0);
diff --git a/src/mame/video/ssrj.cpp b/src/mame/video/ssrj.cpp
index f1add07..0266842 100644
--- a/src/mame/video/ssrj.cpp
+++ b/src/mame/video/ssrj.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 #include "emu.h"
 #include "includes/ssrj.h"
diff --git a/src/mame/video/taito_o.cpp b/src/mame/video/taito_o.cpp
index 6756262..9482c64 100644
--- a/src/mame/video/taito_o.cpp
+++ b/src/mame/video/taito_o.cpp
@@ -1,4 +1,4 @@
-// license:LGPL-2.1+
+// license:BSD-3-Clause
 // copyright-holders:Tomasz Slanina
 /***************************************************************************
 
diff --git a/src/mame/video/tecmo_mix.cpp b/src/mame/video/tecmo_mix.cpp
index 013eed8..4de7535 100644
--- a/src/mame/video/tecmo_mix.cpp
+++ b/src/mame/video/tecmo_mix.cpp
@@ -89,6 +89,28 @@ void tecmo_mix_device::set_bgpen(device_t &device, int bgpen)
 	dev.m_bgpen = bgpen;
 }
 
+uint32_t tecmo_mix_device::sum_colors(const pen_t *pal, int c1_idx, int c2_idx)
+{
+	const pen_t c1 = pal[c1_idx];
+	const pen_t c2 = pal[c2_idx];
+
+	const int c1_a = (c1 >> 24) & 0xFF;
+	const int c1_r = (c1 >> 16) & 0xFF;
+	const int c1_g = (c1 >> 8)  & 0xFF;
+	const int c1_b = c1 & 0xFF;
+
+	const int c2_a = (c2 >> 24) & 0xFF;
+	const int c2_r = (c2 >> 16) & 0xFF;
+	const int c2_g = (c2 >> 8)  & 0xFF;
+	const int c2_b = c2 & 0xFF;
+
+	const uint8_t a = (std::min)(0xFF, c1_a + c2_a);
+	const uint8_t r = (std::min)(0xFF, c1_r + c2_r);
+	const uint8_t g = (std::min)(0xFF, c1_g + c2_g);
+	const uint8_t b = (std::min)(0xFF, c1_b + c2_b);
+
+	return ((a << 24) | (r << 16) | (g << 8) | b);
+}
 
 void tecmo_mix_device::mix_bitmaps(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, palette_device &palette, bitmap_ind16* bitmap_bg, bitmap_ind16* bitmap_fg, bitmap_ind16* bitmap_tx, bitmap_ind16* bitmap_sp)
 {
@@ -113,7 +135,6 @@ void tecmo_mix_device::mix_bitmaps(screen_device &screen, bitmap_rgb32 &bitmap,
 			uint16_t m_sprbln = (sprpixel >> m_sprbln_shift) & 0x1;
 			uint16_t m_sprcol = (sprpixel >> m_sprcol_shift) & 0xf;
 
-
 			sprpixel = (sprpixel & 0xf) | (m_sprcol << 4);
 
 			//sprpixel &= 0xff;
@@ -157,7 +178,6 @@ void tecmo_mix_device::mix_bitmaps(screen_device &screen, bitmap_rgb32 &bitmap,
 							// solid sprite
 							dd[x] = paldata[sprpixel + m_spregular_comp];
 						}
-
 					}
 				}
 				else  if (m_sprpri == (1 ^ m_revspritetile)) // above bg, behind tx, fg
@@ -171,12 +191,12 @@ void tecmo_mix_device::mix_bitmaps(screen_device &screen, bitmap_rgb32 &bitmap,
 								// needs if bgpixel & 0xf check?
 
 								// fg is used and blended with sprite, sprite is used and blended with bg?  -- used on 'trail' of ball when ball is under the transparent area
-								dd[x] = paldata[bgpixel + m_bgblend_comp] + paldata[sprpixel + m_spblend_source]; // WRONG??
+								dd[x] = sum_colors(paldata, bgpixel + m_bgblend_comp, sprpixel + m_spblend_source); // WRONG??
 							}
 							else
 							{
 								// fg is used and blended with opaque sprite
-								dd[x] = paldata[fgpixel + m_fgblend_source] + paldata[sprpixel + m_spblend_comp];
+								dd[x] = sum_colors(paldata, fgpixel + m_fgblend_source, sprpixel + m_spblend_comp);
 							}
 						}
 						else
@@ -184,7 +204,6 @@ void tecmo_mix_device::mix_bitmaps(screen_device &screen, bitmap_rgb32 &bitmap,
 							// fg is used and opaque
 							dd[x] = paldata[fgpixel + m_fgregular_comp];
 						}
-
 					}
 					else
 					{
@@ -193,7 +212,7 @@ void tecmo_mix_device::mix_bitmaps(screen_device &screen, bitmap_rgb32 &bitmap,
 							// needs if bgpixel & 0xf check?
 
 							//fg isn't used, sprite is used and blended with bg? -- used on trail of ball / flippers (looks odd)  -- some ninja gaiden enemy deaths (when behind fg) (looks ok?)  (maybe we need to check for colour saturation?)
-							dd[x] = paldata[bgpixel + m_bgblend_comp] + paldata[sprpixel + m_spblend_source];
+							dd[x] = sum_colors(paldata, bgpixel + m_bgblend_comp, sprpixel + m_spblend_source);
 						}
 						else
 						{
@@ -201,8 +220,6 @@ void tecmo_mix_device::mix_bitmaps(screen_device &screen, bitmap_rgb32 &bitmap,
 							dd[x] = paldata[sprpixel + m_spregular_comp];
 						}
 					}
-
-
 				}
 				else if (m_sprpri == (2 ^ m_revspritetile)) // above bg,fg, behind tx
 				{
@@ -218,18 +235,15 @@ void tecmo_mix_device::mix_bitmaps(screen_device &screen, bitmap_rgb32 &bitmap,
 							else
 							{
 								// blended sprite over solid fgpixel?
-								dd[x] = paldata[fgpixel + m_fgblend_comp] + paldata[sprpixel + m_spblend_source];
+								dd[x] = sum_colors(paldata, fgpixel + m_fgblend_comp, sprpixel + m_spblend_source);
 							}
 						}
 						else // needs if bgpixel & 0xf check?
 						{
 							// blended sprite over solid bg pixel
-							dd[x] = paldata[bgpixel + m_bgblend_comp] + paldata[sprpixel + m_spblend_source];
-						//  dd[x] =  rand();
+							dd[x] = sum_colors(paldata, bgpixel + m_bgblend_comp, sprpixel + m_spblend_source);
+							//  dd[x] =  rand();
 						}
-
-
-
 					}
 					else
 					{
@@ -261,14 +275,13 @@ void tecmo_mix_device::mix_bitmaps(screen_device &screen, bitmap_rgb32 &bitmap,
 					if (fgbln)
 					{
 						// needs if bgpixel & 0xf check?
-						dd[x] = paldata[fgpixel + m_fgblend_source] + paldata[bgpixel + m_bgblend_comp];
+						dd[x] = sum_colors(paldata, fgpixel + m_fgblend_source, bgpixel + m_bgblend_comp);
 
 					}
 					else
 					{
 						dd[x] = paldata[fgpixel + m_fgregular_comp];
 					}
-
 				}
 				else if (bgpixel & 0x0f)
 				{
diff --git a/src/mame/video/tecmo_mix.h b/src/mame/video/tecmo_mix.h
index fdf0a00..b305b63 100644
--- a/src/mame/video/tecmo_mix.h
+++ b/src/mame/video/tecmo_mix.h
@@ -46,9 +46,7 @@ protected:
 	int m_bgpen;
 
 private:
-
-
-
+	uint32_t sum_colors(const pen_t *pal, int c1_idx, int c2_idx);
 };
 
 extern const device_type TECMO_MIXER;
@@ -64,7 +62,7 @@ extern const device_type TECMO_MIXER;
 #define MCFG_TECMO_MIXER_REGULARCOLS(_bgregular_comp, _fgregular_comp, _txregular_comp, _spregular_comp) \
 	tecmo_mix_device::set_regularcols(*device, _bgregular_comp, _fgregular_comp, _txregular_comp, _spregular_comp);
 
-#define MCFG_TECMO_MIXER_BLENDSOUCE(_spblend_source, _fgblend_source) \
+#define MCFG_TECMO_MIXER_BLENDSOURCE(_spblend_source, _fgblend_source) \
 	tecmo_mix_device::set_blendsource(*device, _spblend_source, _fgblend_source);
 
 #define MCFG_TECMO_MIXER_REVSPRITETILE \
diff --git a/src/mame/video/tnzs.cpp b/src/mame/video/tnzs.cpp
index 78bc541..803c39d 100644
--- a/src/mame/video/tnzs.cpp
+++ b/src/mame/video/tnzs.cpp
@@ -31,20 +31,19 @@
 
 ***************************************************************************/
 
-PALETTE_INIT_MEMBER(tnzs_state,arknoid2)
+PALETTE_INIT_MEMBER(tnzs_base_state, prompalette)
 {
 	const uint8_t *color_prom = memregion("proms")->base();
-	int i, col;
 
-	for (i = 0; i < palette.entries(); i++)
+	for (int i = 0; i < palette.entries(); i++)
 	{
-		col = (color_prom[i] << 8) + color_prom[i + 512];
+		int col = (color_prom[i] << 8) + color_prom[i + 512];
 		palette.set_pen_color(i, pal5bit(col >> 10), pal5bit(col >> 5), pal5bit(col >> 0));
 	}
 }
 
 
-uint32_t tnzs_state::screen_update_tnzs(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
+uint32_t tnzs_base_state::screen_update_tnzs(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
 {
 	bitmap.fill(0x1f0, cliprect);
 
@@ -55,7 +54,7 @@ uint32_t tnzs_state::screen_update_tnzs(screen_device &screen, bitmap_ind16 &bit
 	return 0;
 }
 
-void tnzs_state::screen_eof_tnzs(screen_device &screen, bool state)
+void tnzs_base_state::screen_eof_tnzs(screen_device &screen, bool state)
 {
 	// rising edge
 	if (state)
diff --git a/src/mame/video/chihiro.cpp b/src/mame/video/xbox_nv2a.cpp
similarity index 95%
rename from src/mame/video/chihiro.cpp
rename to src/mame/video/xbox_nv2a.cpp
index 1028d4e..0d0e2a9 100644
--- a/src/mame/video/chihiro.cpp
+++ b/src/mame/video/xbox_nv2a.cpp
@@ -4,9 +4,11 @@
 #include "video/poly.h"
 #include "bitmap.h"
 #include "machine/pic8259.h"
-#include "includes/chihiro.h"
+#include "includes/xbox_nv2a.h"
+#include <bitset>
 
 //#define LOG_NV2A
+#define DEBUG_CHECKS // enable for debugging
 
 const char *vertex_program_disassembler::srctypes[] = { "??", "Rn", "Vn", "Cn" };
 const char *vertex_program_disassembler::scaops[] = { "NOP", "IMV", "RCP", "RCC", "RSQ", "EXP", "LOG", "LIT", "???", "???", "???", "???", "???", "???", "???", "???", "???" };
@@ -146,19 +148,23 @@ int vertex_program_disassembler::disassemble_mask(int mask, char *s)
 		return 0;
 	s[0] = '.';
 	l = 1;
-	if ((mask & 8) != 0) {
+	if ((mask & 8) != 0)
+	{
 		s[l] = 'x';
 		l++;
 	}
-	if ((mask & 4) != 0){
+	if ((mask & 4) != 0)
+	{
 		s[l] = 'y';
 		l++;
 	}
-	if ((mask & 2) != 0){
+	if ((mask & 2) != 0)
+	{
 		s[l] = 'z';
 		l++;
 	}
-	if ((mask & 1) != 0){
+	if ((mask & 1) != 0)
+	{
 		s[l] = 'w';
 		l++;
 	}
@@ -909,8 +915,8 @@ void nv2a_renderer::computedilated(void)
 
 	for (b = 0; b < 16; b++)
 		for (a = 0; a < 2048; a++) {
-		dilated0[b][a] = dilate0(a, b);
-		dilated1[b][a] = dilate1(a, b);
+			dilated0[b][a] = dilate0(a, b);
+			dilated1[b][a] = dilate1(a, b);
 		}
 	for (b = 0; b < 16; b++)
 		for (a = 0; a < 16; a++)
@@ -919,6 +925,10 @@ void nv2a_renderer::computedilated(void)
 
 inline uint8_t *nv2a_renderer::direct_access_ptr(offs_t address)
 {
+#ifdef DEBUG_CHECKS
+	if (address >= 512*1024*1024)
+		machine().logerror("Bad address in direct_access_ptr !\n");
+#endif
 	return basemempointer + address;
 }
 
@@ -1267,6 +1277,13 @@ inline uint8_t *nv2a_renderer::read_pixel(int x, int y, int32_t c[4])
 		offset = (dilated0[dilate_rendertarget][x] + dilated1[dilate_rendertarget][y]) * bytespixel_rendertarget;
 	else // type_rendertarget == LINEAR
 		offset = pitch_rendertarget * y + x * bytespixel_rendertarget;
+#ifdef DEBUG_CHECKS
+	if (offset >= size_rendertarget)
+	{
+		machine().logerror("Bad offset computed in read_pixel !\n");
+		offset = 0;
+	}
+#endif
 	switch (colorformat_rendertarget) {
 	case NV2A_COLOR_FORMAT::R5G6B5:
 		addr16 = (uint16_t *)((uint8_t *)rendertarget + offset);
@@ -1317,13 +1334,20 @@ void nv2a_renderer::write_pixel(int x, int y, uint32_t color, int depth)
 	bool stencil_passed;
 	bool depth_passed;
 
-	if ((depth > 0xffffff) || (depth < 0))
+	if ((depth > 0xffffff) || (depth < 0) || (x < 0))
 		return;
 	fb[3] = fb[2] = fb[1] = fb[0] = 0;
 	addr = nullptr;
 	if (color_mask != 0)
 		addr = read_pixel(x, y, fb);
 	if (depthformat_rendertarget == NV2A_RT_DEPTH_FORMAT::Z24S8) {
+#ifdef DEBUG_CHECKS
+		if (((pitch_depthbuffer / 4) * y + x) >= size_depthbuffer)
+		{
+			machine().logerror("Bad depthbuffer offset computed in write_pixel !\n");
+			return;
+		}
+#endif
 		daddr32 = depthbuffer + (pitch_depthbuffer / 4) * y + x;
 		deptsten = *daddr32;
 		dep = deptsten >> 8;
@@ -1331,6 +1355,13 @@ void nv2a_renderer::write_pixel(int x, int y, uint32_t color, int depth)
 		daddr16 = nullptr;
 	}
 	else if (depthformat_rendertarget == NV2A_RT_DEPTH_FORMAT::Z16) {
+#ifdef DEBUG_CHECKS
+		if (((pitch_depthbuffer / 2) * y + x) >= size_depthbuffer)
+		{
+			machine().logerror("Bad depthbuffer offset computed in write_pixel !\n");
+			return;
+		}
+#endif
 		daddr16 = (uint16_t *)depthbuffer + (pitch_depthbuffer / 2) * y + x;
 		deptsten = *daddr16;
 		dep = (deptsten << 8) | 0xff;
@@ -1907,23 +1938,29 @@ void nv2a_renderer::write_pixel(int x, int y, uint32_t color, int depth)
 
 void nv2a_renderer::render_color(int32_t scanline, const extent_t &extent, const nvidia_object_data &objectdata, int threadid)
 {
-	int x;
+	int x, lx;
 
-	if ((extent.startx < 0) || (extent.stopx > 640*4))
+	lx = limits_rendertarget.right();
+	if ((extent.startx < 0) && (extent.stopx <= 0))
+		return;
+	if ((extent.startx > lx) && (extent.stopx > lx))
 		return;
-	x = extent.stopx - extent.startx - 1; // number of pixels to draw
+	x = extent.stopx - extent.startx; // number of pixels to draw (start inclusive, end exclusive)
+	if (extent.stopx > lx)
+		x = x - (extent.stopx - lx - 1);
+	x--;
 	while (x >= 0) {
 		uint32_t a8r8g8b8;
 		int z;
 		int ca, cr, cg, cb;
 		int xp = extent.startx + x; // x coordinate of current pixel
 
-		cb = ((extent.param[(int)VERTEX_PARAMETER::PARAM_COLOR_B].start + (float)x*extent.param[(int)VERTEX_PARAMETER::PARAM_COLOR_B].dpdx))*255.0f;
-		cg = ((extent.param[(int)VERTEX_PARAMETER::PARAM_COLOR_G].start + (float)x*extent.param[(int)VERTEX_PARAMETER::PARAM_COLOR_G].dpdx))*255.0f;
-		cr = ((extent.param[(int)VERTEX_PARAMETER::PARAM_COLOR_R].start + (float)x*extent.param[(int)VERTEX_PARAMETER::PARAM_COLOR_R].dpdx))*255.0f;
-		ca = ((extent.param[(int)VERTEX_PARAMETER::PARAM_COLOR_A].start + (float)x*extent.param[(int)VERTEX_PARAMETER::PARAM_COLOR_A].dpdx))*255.0f;
+		cb = ((extent.param[(int)VERTEX_PARAMETER::PARAM_COLOR_B].start + (double)x*extent.param[(int)VERTEX_PARAMETER::PARAM_COLOR_B].dpdx))*255.0f;
+		cg = ((extent.param[(int)VERTEX_PARAMETER::PARAM_COLOR_G].start + (double)x*extent.param[(int)VERTEX_PARAMETER::PARAM_COLOR_G].dpdx))*255.0f;
+		cr = ((extent.param[(int)VERTEX_PARAMETER::PARAM_COLOR_R].start + (double)x*extent.param[(int)VERTEX_PARAMETER::PARAM_COLOR_R].dpdx))*255.0f;
+		ca = ((extent.param[(int)VERTEX_PARAMETER::PARAM_COLOR_A].start + (double)x*extent.param[(int)VERTEX_PARAMETER::PARAM_COLOR_A].dpdx))*255.0f;
 		a8r8g8b8 = (ca << 24) + (cr << 16) + (cg << 8) + cb; // pixel color obtained by interpolating the colors of the vertices
-		z = (extent.param[(int)VERTEX_PARAMETER::PARAM_Z].start + (float)x*extent.param[(int)VERTEX_PARAMETER::PARAM_Z].dpdx);
+		z = (extent.param[(int)VERTEX_PARAMETER::PARAM_Z].start + (double)x*extent.param[(int)VERTEX_PARAMETER::PARAM_Z].dpdx);
 		write_pixel(xp, scanline, a8r8g8b8, z);
 		x--;
 	}
@@ -1931,30 +1968,36 @@ void nv2a_renderer::render_color(int32_t scanline, const extent_t &extent, const
 
 void nv2a_renderer::render_texture_simple(int32_t scanline, const extent_t &extent, const nvidia_object_data &objectdata, int threadid)
 {
-	int x;
+	int x, lx;
 	uint32_t a8r8g8b8;
-	int z;
 
 	if (!objectdata.data->texture[0].enabled) {
 		return;
 	}
-	if ((extent.startx < 0) || (extent.stopx > 640*4))
+	lx = limits_rendertarget.right();
+	if ((extent.startx < 0) && (extent.stopx <= 0))
 		return;
-	x = extent.stopx - extent.startx - 1;
+	if ((extent.startx > lx) && (extent.stopx > lx))
+		return;
+	x = extent.stopx - extent.startx; // number of pixels to draw (start inclusive, end exclusive)
+	if (extent.stopx > lx)
+		x = x - (extent.stopx - lx - 1);
+	x--;
 	while (x >= 0) {
 		int up, vp;
+		int z;
 		int xp = extent.startx + x; // x coordinate of current pixel
 
 		if (objectdata.data->texture[0].rectangle == false) {
-			up = (extent.param[(int)VERTEX_PARAMETER::PARAM_TEXTURE0_U].start + (float)x*extent.param[(int)VERTEX_PARAMETER::PARAM_TEXTURE0_U].dpdx)*(float)(objectdata.data->texture[0].sizeu - 1); // x coordinate of texel in texture
-			vp = (extent.param[(int)VERTEX_PARAMETER::PARAM_TEXTURE0_V].start + (float)x*extent.param[(int)VERTEX_PARAMETER::PARAM_TEXTURE0_V].dpdx)*(float)(objectdata.data->texture[0].sizev - 1); // y coordinate of texel in texture
+			up = (extent.param[(int)VERTEX_PARAMETER::PARAM_TEXTURE0_U].start + (double)x*extent.param[(int)VERTEX_PARAMETER::PARAM_TEXTURE0_U].dpdx)*(double)(objectdata.data->texture[0].sizeu - 1); // x coordinate of texel in texture
+			vp = (extent.param[(int)VERTEX_PARAMETER::PARAM_TEXTURE0_V].start + (double)x*extent.param[(int)VERTEX_PARAMETER::PARAM_TEXTURE0_V].dpdx)*(double)(objectdata.data->texture[0].sizev - 1); // y coordinate of texel in texture
 		} else
 		{
-			up = extent.param[(int)VERTEX_PARAMETER::PARAM_TEXTURE0_U].start + (float)x*extent.param[(int)VERTEX_PARAMETER::PARAM_TEXTURE0_U].dpdx; // x coordinate of texel in texture
-			vp = extent.param[(int)VERTEX_PARAMETER::PARAM_TEXTURE0_V].start + (float)x*extent.param[(int)VERTEX_PARAMETER::PARAM_TEXTURE0_V].dpdx; // y coordinate of texel in texture
+			up = extent.param[(int)VERTEX_PARAMETER::PARAM_TEXTURE0_U].start + (double)x*extent.param[(int)VERTEX_PARAMETER::PARAM_TEXTURE0_U].dpdx; // x coordinate of texel in texture
+			vp = extent.param[(int)VERTEX_PARAMETER::PARAM_TEXTURE0_V].start + (double)x*extent.param[(int)VERTEX_PARAMETER::PARAM_TEXTURE0_V].dpdx; // y coordinate of texel in texture
 		}
 		a8r8g8b8 = texture_get_texel(0, up, vp);
-		z = (extent.param[(int)VERTEX_PARAMETER::PARAM_Z].start + (float)x*extent.param[(int)VERTEX_PARAMETER::PARAM_Z].dpdx);
+		z = (extent.param[(int)VERTEX_PARAMETER::PARAM_Z].start + (double)x*extent.param[(int)VERTEX_PARAMETER::PARAM_Z].dpdx);
 		write_pixel(xp, scanline, a8r8g8b8, z);
 		x--;
 	}
@@ -1962,7 +2005,7 @@ void nv2a_renderer::render_texture_simple(int32_t scanline, const extent_t &exte
 
 void nv2a_renderer::render_register_combiners(int32_t scanline, const extent_t &extent, const nvidia_object_data &objectdata, int threadid)
 {
-	int x, xp;
+	int x, lx, xp;
 	int up, vp;
 	int ca, cr, cg, cb;
 	uint32_t color[6];
@@ -1972,30 +2015,36 @@ void nv2a_renderer::render_register_combiners(int32_t scanline, const extent_t &
 
 	color[0] = color[1] = color[2] = color[3] = color[4] = color[5] = 0;
 
-	if ((extent.startx < 0) || (extent.stopx > 640*4))
+	lx = limits_rendertarget.right();
+	if ((extent.startx < 0) && (extent.stopx <= 0))
 		return;
+	if ((extent.startx > lx) && (extent.stopx > lx))
+		return;
+	x = extent.stopx - extent.startx; // number of pixels to draw (start inclusive, end exclusive)
+	if (extent.stopx > lx)
+		x = x - (extent.stopx - lx - 1);
+	x--;
 	std::lock_guard<std::mutex> lock(combiner.lock); // needed since multithreading is not supported yet
-	x = extent.stopx - extent.startx - 1; // number of pixels to draw
 	while (x >= 0) {
 		xp = extent.startx + x;
 		// 1: fetch data
 		// 1.1: interpolated color from vertices
-		cb = ((extent.param[(int)VERTEX_PARAMETER::PARAM_COLOR_B].start + (float)x*extent.param[(int)VERTEX_PARAMETER::PARAM_COLOR_B].dpdx))*255.0f;
-		cg = ((extent.param[(int)VERTEX_PARAMETER::PARAM_COLOR_G].start + (float)x*extent.param[(int)VERTEX_PARAMETER::PARAM_COLOR_G].dpdx))*255.0f;
-		cr = ((extent.param[(int)VERTEX_PARAMETER::PARAM_COLOR_R].start + (float)x*extent.param[(int)VERTEX_PARAMETER::PARAM_COLOR_R].dpdx))*255.0f;
-		ca = ((extent.param[(int)VERTEX_PARAMETER::PARAM_COLOR_A].start + (float)x*extent.param[(int)VERTEX_PARAMETER::PARAM_COLOR_A].dpdx))*255.0f;
+		cb = ((extent.param[(int)VERTEX_PARAMETER::PARAM_COLOR_B].start + (double)x*extent.param[(int)VERTEX_PARAMETER::PARAM_COLOR_B].dpdx))*255.0f;
+		cg = ((extent.param[(int)VERTEX_PARAMETER::PARAM_COLOR_G].start + (double)x*extent.param[(int)VERTEX_PARAMETER::PARAM_COLOR_G].dpdx))*255.0f;
+		cr = ((extent.param[(int)VERTEX_PARAMETER::PARAM_COLOR_R].start + (double)x*extent.param[(int)VERTEX_PARAMETER::PARAM_COLOR_R].dpdx))*255.0f;
+		ca = ((extent.param[(int)VERTEX_PARAMETER::PARAM_COLOR_A].start + (double)x*extent.param[(int)VERTEX_PARAMETER::PARAM_COLOR_A].dpdx))*255.0f;
 		color[0] = (ca << 24) + (cr << 16) + (cg << 8) + cb; // pixel color obtained by interpolating the colors of the vertices
 		color[1] = 0; // lighting not yet
 		// 1.2: color for each of the 4 possible textures
 		for (n = 0; n < 4; n++) {
 			if (texture[n].enabled) {
 				if (texture[n].rectangle == false) {
-					up = (extent.param[(int)VERTEX_PARAMETER::PARAM_TEXTURE0_U + n * 2].start + (float)x*extent.param[(int)VERTEX_PARAMETER::PARAM_TEXTURE0_U + n * 2].dpdx)*(float)(objectdata.data->texture[n].sizeu - 1);
-					vp = (extent.param[(int)VERTEX_PARAMETER::PARAM_TEXTURE0_V + n * 2].start + (float)x*extent.param[(int)VERTEX_PARAMETER::PARAM_TEXTURE0_V + n * 2].dpdx)*(float)(objectdata.data->texture[n].sizev - 1);
+					up = (extent.param[(int)VERTEX_PARAMETER::PARAM_TEXTURE0_U + n * 2].start + (double)x*extent.param[(int)VERTEX_PARAMETER::PARAM_TEXTURE0_U + n * 2].dpdx)*(double)(objectdata.data->texture[n].sizeu - 1);
+					vp = (extent.param[(int)VERTEX_PARAMETER::PARAM_TEXTURE0_V + n * 2].start + (double)x*extent.param[(int)VERTEX_PARAMETER::PARAM_TEXTURE0_V + n * 2].dpdx)*(double)(objectdata.data->texture[n].sizev - 1);
 				} else
 				{
-					up = extent.param[(int)VERTEX_PARAMETER::PARAM_TEXTURE0_U + n * 2].start + (float)x*extent.param[(int)VERTEX_PARAMETER::PARAM_TEXTURE0_U + n * 2].dpdx;
-					vp = extent.param[(int)VERTEX_PARAMETER::PARAM_TEXTURE0_V + n * 2].start + (float)x*extent.param[(int)VERTEX_PARAMETER::PARAM_TEXTURE0_V + n * 2].dpdx;
+					up = extent.param[(int)VERTEX_PARAMETER::PARAM_TEXTURE0_U + n * 2].start + (double)x*extent.param[(int)VERTEX_PARAMETER::PARAM_TEXTURE0_U + n * 2].dpdx;
+					vp = extent.param[(int)VERTEX_PARAMETER::PARAM_TEXTURE0_V + n * 2].start + (double)x*extent.param[(int)VERTEX_PARAMETER::PARAM_TEXTURE0_V + n * 2].dpdx;
 				}
 				color[n + 2] = texture_get_texel(n, up, vp);
 			}
@@ -2021,7 +2070,7 @@ void nv2a_renderer::render_register_combiners(int32_t scanline, const extent_t &
 		combiner_final_output();
 		a8r8g8b8 = combiner_float_argb8(combiner.output);
 		// 3: write pixel
-		z = (extent.param[(int)VERTEX_PARAMETER::PARAM_Z].start + (float)x*extent.param[(int)VERTEX_PARAMETER::PARAM_Z].dpdx);
+		z = (extent.param[(int)VERTEX_PARAMETER::PARAM_Z].start + (double)x*extent.param[(int)VERTEX_PARAMETER::PARAM_Z].dpdx);
 		write_pixel(xp, scanline, a8r8g8b8, z);
 		x--;
 	}
@@ -2175,7 +2224,6 @@ void nv2a_renderer::read_vertex(address_space & space, offs_t address, vertex_nv
 	l = vertexbuffer_size[attrib];
 	switch (vertexbuffer_kind[attrib]) {
 	case NV2A_VTXBUF_TYPE::FLOAT:
-	default:
 		vertex.attribute[attrib].fv[0] = 0;
 		vertex.attribute[attrib].fv[1] = 0;
 		vertex.attribute[attrib].fv[2] = 0;
@@ -2206,6 +2254,12 @@ void nv2a_renderer::read_vertex(address_space & space, offs_t address, vertex_nv
 		vertex.attribute[attrib].fv[2] = ((u & 0xff0000) >> 16) / 255.0;  // r
 		vertex.attribute[attrib].fv[3] = ((u & 0xff000000) >> 24) / 255.0;  // a
 		break;
+	default:
+		vertex.attribute[attrib].fv[0] = 0;
+		vertex.attribute[attrib].fv[1] = 0;
+		vertex.attribute[attrib].fv[2] = 0;
+		vertex.attribute[attrib].fv[3] = 1.0;
+		machine().logerror("Unsupported vertex type in read_vertex !\n");
 	}
 }
 
@@ -2627,7 +2681,10 @@ uint32_t nv2a_renderer::render_triangle_culling(const rectangle &cliprect, rende
 	if (backface_culling_enabled == false)
 		return render_triangle(cliprect, callback, paramcount, _v1, _v2, _v3);
 	if (backface_culling_culled == NV2A_GL_CULL_FACE::FRONT_AND_BACK)
+	{
+		triangles_bfculled++;
 		return 0;
+	}
 	areax2 = _v1.x*(_v2.y - _v3.y) + _v2.x*(_v3.y - _v1.y) + _v3.x*(_v1.y - _v2.y);
 	if (backface_culling_winding == NV2A_GL_FRONT_FACE::CCW)
 	{
@@ -2648,98 +2705,125 @@ uint32_t nv2a_renderer::render_triangle_culling(const rectangle &cliprect, rende
 	if (face == NV2A_GL_CULL_FACE::BACK)
 		if (backface_culling_culled == NV2A_GL_CULL_FACE::FRONT)
 			return render_triangle(cliprect, callback, paramcount, _v1, _v2, _v3);
+	triangles_bfculled++;
 	return 0;
 }
 
-uint32_t nv2a_renderer::render_triangle_clipping(const rectangle &cliprect, render_delegate callback, int paramcount, nv2avertex_t &_v1, nv2avertex_t &_v2, nv2avertex_t &_v3)
+int nv2a_renderer::clip_triangle_w(nv2avertex_t *vi[3], nv2avertex_t *vo)
 {
-#if 0
-	nv2avertex_t *vi[3];
-	nv2avertex_t vo[16];
 	int idx_prev, idx_curr;
 	int neg_prev, neg_curr;
-	float tfactor;
+	double tfactor;
 	int idx;
-#endif
+	const double wthreshold = 0.000001;
 
-	if ((_v1.w > 0) && (_v2.w > 0) && (_v3.w > 0))
-		return render_triangle_culling(cliprect, callback, paramcount, _v1, _v2, _v3);
-#if 0
-	vi[0] = &_v1;
-	vi[1] = &_v2;
-	vi[2] = &_v3;
-	for (int n=0;n < 3;n++)
-	{
-		// remove translate
-		vi[n]->x = vi[n]->x - translatex;
-		vi[n]->y = vi[n]->y - translatey;
-		vi[n]->p[(int)VERTEX_PARAMETER::PARAM_Z] = vi[n]->p[(int)VERTEX_PARAMETER::PARAM_Z] - translatez;
-		// remove scale
-		vi[n]->x = vi[n]->x / scalex;
-		vi[n]->y = vi[n]->y / scaley;
-		vi[n]->p[(int)VERTEX_PARAMETER::PARAM_Z] = vi[n]->p[(int)VERTEX_PARAMETER::PARAM_Z] / scalez;
-		// remove perspective divide
-		vi[n]->x = vi[n]->x * vi[n]->w;
-		vi[n]->y = vi[n]->y * vi[n]->w;
-		vi[n]->p[(int)VERTEX_PARAMETER::PARAM_Z] = vi[n]->p[(int)VERTEX_PARAMETER::PARAM_Z] * vi[n]->w;
-	}
 	idx_prev = 2;
 	idx_curr = 0;
 	idx = 0;
-	neg_prev = vi[idx_prev]->w < 0.00000001 ? 1 : 0;
+	neg_prev = vi[idx_prev]->w < wthreshold ? 1 : 0;
 	while (idx_curr < 3)
 	{
-		neg_curr = vi[idx_curr]->w < 0.00000001 ? 1 : 0;
+		neg_curr = vi[idx_curr]->w < wthreshold ? 1 : 0;
 		if (neg_curr ^ neg_prev)
 		{
-			float p = (float)0.00000001;
-
-			tfactor = (p - vi[idx_prev]->w) / (vi[idx_curr]->w - vi[idx_prev]->w);
-
+			tfactor = (wthreshold - vi[idx_prev]->w) / (vi[idx_curr]->w - vi[idx_prev]->w);
+			// compute values for the new intermediate point
 			vo[idx].x = ((vi[idx_curr]->x - vi[idx_prev]->x) * tfactor) + vi[idx_prev]->x;
 			vo[idx].y = ((vi[idx_curr]->y - vi[idx_prev]->y) * tfactor) + vi[idx_prev]->y;
 			vo[idx].w = ((vi[idx_curr]->w - vi[idx_prev]->w) * tfactor) + vi[idx_prev]->w;
-			for (int n=0;n < 13;n++)
+			for (int n = 0; n < 13; n++)
 				vo[idx].p[n] = ((vi[idx_curr]->p[n] - vi[idx_prev]->p[n]) * tfactor) + vi[idx_prev]->p[n];
 			idx++;
 		}
 		if (neg_curr == 0)
 		{
-			memcpy(&vo[idx], vi[idx_curr],sizeof(nv2avertex_t));
+			vo[idx].x = vi[idx_curr]->x;
+			vo[idx].y = vi[idx_curr]->y;
+			vo[idx].w = vi[idx_curr]->w;
+			for (int n = 0; n < 13; n++)
+				vo[idx].p[n] = vi[idx_curr]->p[n];
 			idx++;
 		}
 		neg_prev = neg_curr;
 		idx_prev = idx_curr;
 		idx_curr++;
 	}
-	for (int n = 0; n < idx; n++)
+	return idx;
+}
+
+uint32_t nv2a_renderer::render_triangle_clipping(const rectangle &cliprect, render_delegate callback, int paramcount, nv2avertex_t &_v1, nv2avertex_t &_v2, nv2avertex_t &_v3)
+{
+#if 0
+	nv2avertex_t *vi[3];
+	nv2avertex_t vo[16];
+	int nv;
+#endif
+
+	if ((_v1.w > 0) && (_v2.w > 0) && (_v3.w > 0))
+		return render_triangle_culling(cliprect, callback, paramcount, _v1, _v2, _v3);
+#if 0
+	// assign the elements of the array
+	vi[0] = &_v1;
+	vi[1] = &_v2;
+	vi[2] = &_v3;
+	// go back to the state before perpective divide
+	if (vertex_pipeline == 4)
+	{
+		for (int n = 0; n < 3; n++)
+		{
+			vi[n]->x = (vi[n]->x / (double)supersample_factor_x)*vi[n]->w;
+			vi[n]->y = (vi[n]->y / (double)supersample_factor_y)*vi[n]->w;
+			vi[n]->p[(int)VERTEX_PARAMETER::PARAM_Z] = vi[n]->p[(int)VERTEX_PARAMETER::PARAM_Z] * vi[n]->w;
+		}
+	} else
+	{
+		for (int n = 0; n < 3; n++)
+		{
+			// remove translate
+			vi[n]->x = vi[n]->x - matrix.translate[0];
+			vi[n]->y = vi[n]->y - matrix.translate[1];
+			vi[n]->p[(int)VERTEX_PARAMETER::PARAM_Z] = vi[n]->p[(int)VERTEX_PARAMETER::PARAM_Z] - matrix.translate[2];
+			// remove perspective divide
+			vi[n]->x = vi[n]->x * vi[n]->w;
+			vi[n]->y = vi[n]->y * vi[n]->w;
+			vi[n]->p[(int)VERTEX_PARAMETER::PARAM_Z] = vi[n]->p[(int)VERTEX_PARAMETER::PARAM_Z] * vi[n]->w;
+		}
+	}
+	// do the clipping
+	nv = clip_triangle_w(vi, vo);
+	// screen coordinates for the new points
+	if (vertex_pipeline == 4)
 	{
-		// apply perspective divide
-		vo[n].x = vo[n].x / vo[n].w;
-		vo[n].y = vo[n].y / vo[n].w;
-		vo[n].p[(int)VERTEX_PARAMETER::PARAM_Z] = vo[n].p[(int)VERTEX_PARAMETER::PARAM_Z] / vo[n].w;
-		// apply scale
-		vo[n].x = vo[n].x * scalex;
-		vo[n].y = vo[n].y * scaley;
-		vo[n].p[(int)VERTEX_PARAMETER::PARAM_Z] = vo[n].p[(int)VERTEX_PARAMETER::PARAM_Z] * scalez;
-		// apply translate
-		vo[n].x = vo[n].x + translatex;
-		vo[n].y = vo[n].y + translatey;
-		vo[n].p[(int)VERTEX_PARAMETER::PARAM_Z] = vo[n].p[(int)VERTEX_PARAMETER::PARAM_Z] + translatez;
-	}
-	for (int n = 0; n < (idx-2); n++)
+		for (int n = 0; n < nv; n++)
+		{
+			vo[n].x = vo[n].x*(double)supersample_factor_x / vo[n].w;
+			vo[n].y = vo[n].y*(double)supersample_factor_y / vo[n].w;
+			vo[n].p[(int)VERTEX_PARAMETER::PARAM_Z] = vo[n].p[(int)VERTEX_PARAMETER::PARAM_Z] / vo[n].w;
+		}
+	} else
 	{
-		if ((n & 1) == 0)
-			render_triangle_culling(cliprect, callback, paramcount, vo[n], vo[n + 1], vo[n + 2]);
-		else
-			render_triangle_culling(cliprect, callback, paramcount, vo[n], vo[n + 2], vo[n + 1]);
+		for (int n = 0; n < nv; n++)
+		{
+			// apply perspective divide
+			vo[n].x = vo[n].x / vo[n].w;
+			vo[n].y = vo[n].y / vo[n].w;
+			vo[n].p[(int)VERTEX_PARAMETER::PARAM_Z] = vo[n].p[(int)VERTEX_PARAMETER::PARAM_Z] / vo[n].w;
+			// apply translate
+			vo[n].x = vo[n].x + matrix.translate[0];
+			vo[n].y = vo[n].y + matrix.translate[1];
+			vo[n].p[(int)VERTEX_PARAMETER::PARAM_Z] = vo[n].p[(int)VERTEX_PARAMETER::PARAM_Z] + matrix.translate[2];
+		}
 	}
+	for (int n = 1; n <= (nv - 2); n++)
+		render_triangle_culling(cliprect, callback, paramcount, vo[0], vo[n], vo[n + 1]);
 #endif
 	return 0;
 }
 
 void nv2a_renderer::assemble_primitive(vertex_nv *source, int count, render_delegate &renderspans)
 {
+	uint32_t pc = primitives_count;
+
 	for (; count > 0; count--) {
 		if (primitive_type == NV2A_BEGIN_END::QUADS) {
 			convert_vertices_poly(source, vertex_xy + vertex_count + vertex_accumulated, 1);
@@ -2847,6 +2931,7 @@ void nv2a_renderer::assemble_primitive(vertex_nv *source, int count, render_dele
 			vertex_count++;
 		}
 	}
+	primitives_total_count += primitives_count - pc;
 }
 
 void nv2a_renderer::compute_limits_rendertarget(uint32_t chanel, uint32_t subchannel)
@@ -2869,6 +2954,12 @@ void nv2a_renderer::compute_limits_rendertarget(uint32_t chanel, uint32_t subcha
 	limits_rendertarget.sety(y, y + h - 1);
 }
 
+void nv2a_renderer::compute_size_rendertarget(uint32_t chanel, uint32_t subchannel)
+{
+	size_rendertarget = pitch_rendertarget*(limits_rendertarget.bottom() + 1);
+	size_depthbuffer = pitch_depthbuffer*(limits_rendertarget.bottom() + 1);
+}
+
 int nv2a_renderer::geforce_exec_method(address_space & space, uint32_t chanel, uint32_t subchannel, uint32_t method, uint32_t address, int &countlen)
 {
 	uint32_t maddress;
@@ -3037,7 +3128,7 @@ int nv2a_renderer::geforce_exec_method(address_space & space, uint32_t chanel, u
 	}
 	if ((maddress >= 0x1980) && (maddress < 0x1a00))
 	{
-		int v = maddress - 0x1980; // 16 couples,4 values per couple
+		int v = maddress - 0x1980; // 16 couples,4 values per couple,16*2*4=128
 		int attr = v >> 3;
 		int comp = (v >> 1) & 2;
 		uint16_t d1 = data & 0xffff;
@@ -3192,9 +3283,11 @@ int nv2a_renderer::geforce_exec_method(address_space & space, uint32_t chanel, u
 	}
 	if (maddress == 0x0200) {
 		compute_limits_rendertarget(chanel, subchannel);
+		compute_size_rendertarget(chanel, subchannel);
 	}
 	if (maddress == 0x0204) {
 		compute_limits_rendertarget(chanel, subchannel);
+		compute_size_rendertarget(chanel, subchannel);
 	}
 	if (maddress == 0x0208) {
 		log2height_rendertarget = (data >> 24) & 255;
@@ -3205,6 +3298,7 @@ int nv2a_renderer::geforce_exec_method(address_space & space, uint32_t chanel, u
 		colorformat_rendertarget = (NV2A_COLOR_FORMAT)((data >> 0) & 15);
 		compute_supersample_factors(supersample_factor_x, supersample_factor_y);
 		compute_limits_rendertarget(chanel, subchannel);
+		compute_size_rendertarget(chanel, subchannel);
 		switch (colorformat_rendertarget) {
 		case NV2A_COLOR_FORMAT::R5G6B5:
 			bytespixel_rendertarget = 2;
@@ -3227,6 +3321,7 @@ int nv2a_renderer::geforce_exec_method(address_space & space, uint32_t chanel, u
 	if (maddress == 0x020c) {
 		pitch_rendertarget=data & 0xffff;
 		pitch_depthbuffer=(data >> 16) & 0xffff;
+		compute_size_rendertarget(chanel, subchannel);
 #ifdef LOG_NV2A
 		printf("Pitch color %04X zbuffer %04X\n\r", pitch_rendertarget, pitch_depthbuffer);
 #endif
diff --git a/src/mame/video/yunsung8.cpp b/src/mame/video/yunsung8.cpp
index 2d1645d..ca18599 100644
--- a/src/mame/video/yunsung8.cpp
+++ b/src/mame/video/yunsung8.cpp
@@ -58,9 +58,9 @@ READ8_MEMBER(yunsung8_state::videoram_r)
 		bank = m_videobank & 1;
 
 	if (bank)
-		return m_videoram_0[offset];
+		return m_bg_vram[offset];
 	else
-		return m_videoram_1[offset];
+		return m_fg_vram[offset];
 }
 
 
@@ -73,9 +73,9 @@ WRITE8_MEMBER(yunsung8_state::videoram_w)
 		int color;
 
 		if (bank)
-			RAM = m_videoram_0;
+			RAM = m_bg_vram;
 		else
-			RAM = m_videoram_1;
+			RAM = m_fg_vram;
 
 		RAM[offset] = data;
 		color = RAM[offset & ~1] | (RAM[offset | 1] << 8);
@@ -95,13 +95,13 @@ WRITE8_MEMBER(yunsung8_state::videoram_w)
 
 		if (bank)
 		{
-			m_videoram_0[offset] = data;
-			m_tilemap_0->mark_tile_dirty(tile);
+			m_bg_vram[offset] = data;
+			m_bg_tilemap->mark_tile_dirty(tile);
 		}
 		else
 		{
-			m_videoram_1[offset] = data;
-			m_tilemap_1->mark_tile_dirty(tile);
+			m_fg_vram[offset] = data;
+			m_fg_tilemap->mark_tile_dirty(tile);
 		}
 	}
 }
@@ -132,10 +132,11 @@ WRITE8_MEMBER(yunsung8_state::flipscreen_w)
 #define DIM_NX_0            (0x40)
 #define DIM_NY_0            (0x20)
 
-TILE_GET_INFO_MEMBER(yunsung8_state::get_tile_info_0)
+TILE_GET_INFO_MEMBER(yunsung8_state::get_bg_tile_info)
 {
-	int code  =  m_videoram_0[0x1000 + tile_index * 2 + 0] + m_videoram_0[0x1000 + tile_index * 2 + 1] * 256;
-	int color =  m_videoram_0[0x0800 + tile_index] & 0x07;
+	int code  =  m_bg_vram[0x1000 + tile_index * 2 + 0] + m_bg_vram[0x1000 + tile_index * 2 + 1] * 256;
+	int color =  m_bg_vram[0x0800 + tile_index] & 0x07;
+
 	SET_TILE_INFO_MEMBER(0,
 			code,
 			color,
@@ -147,10 +148,11 @@ TILE_GET_INFO_MEMBER(yunsung8_state::get_tile_info_0)
 #define DIM_NX_1            (0x40)
 #define DIM_NY_1            (0x20)
 
-TILE_GET_INFO_MEMBER(yunsung8_state::get_tile_info_1)
+TILE_GET_INFO_MEMBER(yunsung8_state::get_fg_tile_info)
 {
-	int code  =  m_videoram_1[0x1000 + tile_index * 2 + 0] + m_videoram_1[0x1000 + tile_index * 2 + 1] * 256;
-	int color =  m_videoram_1[0x0800 + tile_index] & 0x3f;
+	int code  =  m_fg_vram[0x1000 + tile_index * 2 + 0] + m_fg_vram[0x1000 + tile_index * 2 + 1] * 256;
+	int color =  m_fg_vram[0x0800 + tile_index] & 0x3f;
+
 	SET_TILE_INFO_MEMBER(1,
 			code,
 			color,
@@ -170,10 +172,10 @@ TILE_GET_INFO_MEMBER(yunsung8_state::get_tile_info_1)
 
 void yunsung8_state::video_start()
 {
-	m_tilemap_0 = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(yunsung8_state::get_tile_info_0),this), TILEMAP_SCAN_ROWS, 8, 8, DIM_NX_0, DIM_NY_0 );
-	m_tilemap_1 = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(yunsung8_state::get_tile_info_1),this), TILEMAP_SCAN_ROWS, 8, 8, DIM_NX_1, DIM_NY_1 );
+	m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(yunsung8_state::get_bg_tile_info),this), TILEMAP_SCAN_ROWS, 8, 8, DIM_NX_0, DIM_NY_0 );
+	m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(yunsung8_state::get_fg_tile_info),this), TILEMAP_SCAN_ROWS, 8, 8, DIM_NX_1, DIM_NY_1 );
 
-	m_tilemap_1->set_transparent_pen(0);
+	m_fg_tilemap->set_transparent_pen(0);
 }
 
 
@@ -201,12 +203,12 @@ if (machine().input().code_pressed(KEYCODE_Z))
 #endif
 
 	if (layers_ctrl & 1)
-		m_tilemap_0->draw(screen, bitmap, cliprect, 0, 0);
+		m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
 	else
 		bitmap.fill(0, cliprect);
 
 	if (layers_ctrl & 2)
-		m_tilemap_1->draw(screen, bitmap, cliprect, 0, 0);
+		m_fg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
 
 	return 0;
 }
diff --git a/src/osd/modules/debugger/debugimgui.cpp b/src/osd/modules/debugger/debugimgui.cpp
index def4d06..8c48d1a 100644
--- a/src/osd/modules/debugger/debugimgui.cpp
+++ b/src/osd/modules/debugger/debugimgui.cpp
@@ -1000,6 +1000,7 @@ void debug_imgui::refresh_filelist()
 	util::zippath_directory* dir = nullptr;
 	const char *volume_name;
 	const osd::directory::entry *dirent;
+	uint8_t first = 0;
 
 	// todo
 	m_filelist.clear();
@@ -1019,6 +1020,7 @@ void debug_imgui::refresh_filelist()
 			m_filelist.emplace_back(std::move(temp));
 			x++;
 		}
+		first = m_filelist.size();
 		while((dirent = util::zippath_readdir(dir)) != nullptr)
 		{
 			file_entry temp;
@@ -1040,6 +1042,9 @@ void debug_imgui::refresh_filelist()
 	}
 	if (dir != nullptr)
 		util::zippath_closedir(dir);
+
+	// sort file list, as it is not guaranteed to be in any particular order
+	std::sort(m_filelist.begin()+first,m_filelist.end(),[](file_entry x, file_entry y) { return x.basename < y.basename; } );
 }
 
 void debug_imgui::refresh_typelist()
@@ -1378,7 +1383,7 @@ void debug_imgui::update()
 	ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabHovered,ImVec4(0.7f,0.7f,0.7f,0.8f));
 	ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabActive,ImVec4(0.9f,0.9f,0.9f,0.8f));
 	ImGui::PushStyleColor(ImGuiCol_Border,ImVec4(0.7f,0.7f,0.7f,0.8f));
-
+	ImGui::PushStyleColor(ImGuiCol_ComboBg,ImVec4(0.4f,0.4f,0.4f,0.9f));
 	m_text_size = ImGui::CalcTextSize("A");  // hopefully you're using a monospaced font...
 	draw_console();  // We'll always have a console window
 
@@ -1420,7 +1425,7 @@ void debug_imgui::update()
 		global_free(to_delete);
 	}
 
-	ImGui::PopStyleColor(12);
+	ImGui::PopStyleColor(13);
 }
 
 void debug_imgui::init_debugger(running_machine &machine)
diff --git a/src/osd/modules/debugger/debugqt.cpp b/src/osd/modules/debugger/debugqt.cpp
index ff53278..c138aa0 100644
--- a/src/osd/modules/debugger/debugqt.cpp
+++ b/src/osd/modules/debugger/debugqt.cpp
@@ -77,10 +77,10 @@ static MainWindow* mainQtWindow = nullptr;
 std::vector<WindowQtConfig*> xmlConfigurations;
 
 
-static void xml_configuration_load(running_machine &machine, config_type cfg_type, xml_data_node *parentnode)
+static void xml_configuration_load(running_machine &machine, config_type cfg_type, util::xml::data_node const *parentnode)
 {
 	// We only care about game files
-	if (cfg_type != config_type::CONFIG_TYPE_GAME)
+	if (cfg_type != config_type::GAME)
 		return;
 
 	// Might not have any data
@@ -92,7 +92,7 @@ static void xml_configuration_load(running_machine &machine, config_type cfg_typ
 	xmlConfigurations.clear();
 
 	// Configuration load
-	xml_data_node const * wnode = nullptr;
+	util::xml::data_node const * wnode = nullptr;
 	for (wnode = parentnode->get_child("window"); wnode != nullptr; wnode = wnode->get_next_sibling("window"))
 	{
 		WindowQtConfig::WindowType type = (WindowQtConfig::WindowType)wnode->get_attribute_int("type", WindowQtConfig::WIN_TYPE_UNKNOWN);
@@ -112,10 +112,10 @@ static void xml_configuration_load(running_machine &machine, config_type cfg_typ
 }
 
 
-static void xml_configuration_save(running_machine &machine, config_type cfg_type, xml_data_node *parentnode)
+static void xml_configuration_save(running_machine &machine, config_type cfg_type, util::xml::data_node *parentnode)
 {
 	// We only write to game configurations
-	if (cfg_type != config_type::CONFIG_TYPE_GAME)
+	if (cfg_type != config_type::GAME)
 		return;
 
 	for (int i = 0; i < xmlConfigurations.size(); i++)
@@ -123,7 +123,7 @@ static void xml_configuration_save(running_machine &machine, config_type cfg_typ
 		WindowQtConfig* config = xmlConfigurations[i];
 
 		// Create an xml node
-		xml_data_node *const debugger_node = parentnode->add_child("window", nullptr);
+		util::xml::data_node *const debugger_node = parentnode->add_child("window", nullptr);
 		if (debugger_node == nullptr)
 			continue;
 
@@ -268,8 +268,8 @@ void debug_qt::init_debugger(running_machine &machine)
 	m_machine = &machine;
 	// Setup the configuration XML saving and loading
 	machine.configuration().config_register("debugger",
-					config_saveload_delegate(&xml_configuration_load, &machine),
-					config_saveload_delegate(&xml_configuration_save, &machine));
+					config_load_delegate(&xml_configuration_load, &machine),
+					config_save_delegate(&xml_configuration_save, &machine));
 }
 
 
diff --git a/src/osd/modules/debugger/qt/breakpointswindow.cpp b/src/osd/modules/debugger/qt/breakpointswindow.cpp
index a5b06ec..029cf2d 100644
--- a/src/osd/modules/debugger/qt/breakpointswindow.cpp
+++ b/src/osd/modules/debugger/qt/breakpointswindow.cpp
@@ -122,14 +122,14 @@ void BreakpointsWindowQtConfig::applyToQWidget(QWidget* widget)
 }
 
 
-void BreakpointsWindowQtConfig::addToXmlDataNode(xml_data_node &node) const
+void BreakpointsWindowQtConfig::addToXmlDataNode(util::xml::data_node &node) const
 {
 	WindowQtConfig::addToXmlDataNode(node);
 	node.set_attribute_int("bwtype", m_bwType);
 }
 
 
-void BreakpointsWindowQtConfig::recoverFromXmlNode(xml_data_node const &node)
+void BreakpointsWindowQtConfig::recoverFromXmlNode(util::xml::data_node const &node)
 {
 	WindowQtConfig::recoverFromXmlNode(node);
 	m_bwType = node.get_attribute_int("bwtype", m_bwType);
diff --git a/src/osd/modules/debugger/qt/breakpointswindow.h b/src/osd/modules/debugger/qt/breakpointswindow.h
index 52d61e9..60bbdc4 100644
--- a/src/osd/modules/debugger/qt/breakpointswindow.h
+++ b/src/osd/modules/debugger/qt/breakpointswindow.h
@@ -48,8 +48,8 @@ public:
 
 	void buildFromQWidget(QWidget* widget);
 	void applyToQWidget(QWidget* widget);
-	void addToXmlDataNode(xml_data_node &node) const;
-	void recoverFromXmlNode(xml_data_node const &node);
+	void addToXmlDataNode(util::xml::data_node &node) const;
+	void recoverFromXmlNode(util::xml::data_node const &node);
 };
 
 
diff --git a/src/osd/modules/debugger/qt/dasmwindow.cpp b/src/osd/modules/debugger/qt/dasmwindow.cpp
index c317c41..fd98a64 100644
--- a/src/osd/modules/debugger/qt/dasmwindow.cpp
+++ b/src/osd/modules/debugger/qt/dasmwindow.cpp
@@ -302,14 +302,14 @@ void DasmWindowQtConfig::applyToQWidget(QWidget* widget)
 	rightBarGroup->actions()[m_rightBar]->trigger();
 }
 
-void DasmWindowQtConfig::addToXmlDataNode(xml_data_node &node) const
+void DasmWindowQtConfig::addToXmlDataNode(util::xml::data_node &node) const
 {
 	WindowQtConfig::addToXmlDataNode(node);
 	node.set_attribute_int("cpu", m_cpu);
 	node.set_attribute_int("rightbar", m_rightBar);
 }
 
-void DasmWindowQtConfig::recoverFromXmlNode(xml_data_node const &node)
+void DasmWindowQtConfig::recoverFromXmlNode(util::xml::data_node const &node)
 {
 	WindowQtConfig::recoverFromXmlNode(node);
 	m_cpu = node.get_attribute_int("cpu", m_cpu);
diff --git a/src/osd/modules/debugger/qt/dasmwindow.h b/src/osd/modules/debugger/qt/dasmwindow.h
index 9a8bf84..27b652c 100644
--- a/src/osd/modules/debugger/qt/dasmwindow.h
+++ b/src/osd/modules/debugger/qt/dasmwindow.h
@@ -71,8 +71,8 @@ public:
 
 	void buildFromQWidget(QWidget* widget);
 	void applyToQWidget(QWidget* widget);
-	void addToXmlDataNode(xml_data_node &node) const;
-	void recoverFromXmlNode(xml_data_node const &node);
+	void addToXmlDataNode(util::xml::data_node &node) const;
+	void recoverFromXmlNode(util::xml::data_node const &node);
 };
 
 
diff --git a/src/osd/modules/debugger/qt/deviceinformationwindow.cpp b/src/osd/modules/debugger/qt/deviceinformationwindow.cpp
index aa71d02..30daaae 100644
--- a/src/osd/modules/debugger/qt/deviceinformationwindow.cpp
+++ b/src/osd/modules/debugger/qt/deviceinformationwindow.cpp
@@ -122,14 +122,14 @@ void DeviceInformationWindowQtConfig::applyToQWidget(QWidget* widget)
 }
 
 
-void DeviceInformationWindowQtConfig::addToXmlDataNode(xml_data_node &node) const
+void DeviceInformationWindowQtConfig::addToXmlDataNode(util::xml::data_node &node) const
 {
 	WindowQtConfig::addToXmlDataNode(node);
 	node.set_attribute("device-tag", m_device_tag.c_str());
 }
 
 
-void DeviceInformationWindowQtConfig::recoverFromXmlNode(xml_data_node const &node)
+void DeviceInformationWindowQtConfig::recoverFromXmlNode(util::xml::data_node const &node)
 {
 	WindowQtConfig::recoverFromXmlNode(node);
 	m_device_tag = node.get_attribute_string("device-tag", ":");
diff --git a/src/osd/modules/debugger/qt/deviceinformationwindow.h b/src/osd/modules/debugger/qt/deviceinformationwindow.h
index 05335b6..5ed1bfb 100644
--- a/src/osd/modules/debugger/qt/deviceinformationwindow.h
+++ b/src/osd/modules/debugger/qt/deviceinformationwindow.h
@@ -45,8 +45,8 @@ public:
 
 	void buildFromQWidget(QWidget* widget);
 	void applyToQWidget(QWidget* widget);
-	void addToXmlDataNode(xml_data_node &node) const;
-	void recoverFromXmlNode(xml_data_node const &node);
+	void addToXmlDataNode(util::xml::data_node &node) const;
+	void recoverFromXmlNode(util::xml::data_node const &node);
 };
 
 
diff --git a/src/osd/modules/debugger/qt/deviceswindow.cpp b/src/osd/modules/debugger/qt/deviceswindow.cpp
index 4c57025..599022f 100644
--- a/src/osd/modules/debugger/qt/deviceswindow.cpp
+++ b/src/osd/modules/debugger/qt/deviceswindow.cpp
@@ -164,13 +164,13 @@ void DevicesWindowQtConfig::applyToQWidget(QWidget* widget)
 }
 
 
-void DevicesWindowQtConfig::addToXmlDataNode(xml_data_node &node) const
+void DevicesWindowQtConfig::addToXmlDataNode(util::xml::data_node &node) const
 {
 	WindowQtConfig::addToXmlDataNode(node);
 }
 
 
-void DevicesWindowQtConfig::recoverFromXmlNode(xml_data_node const &node)
+void DevicesWindowQtConfig::recoverFromXmlNode(util::xml::data_node const &node)
 {
 	WindowQtConfig::recoverFromXmlNode(node);
 }
diff --git a/src/osd/modules/debugger/qt/deviceswindow.h b/src/osd/modules/debugger/qt/deviceswindow.h
index e2440d6..87e710a 100644
--- a/src/osd/modules/debugger/qt/deviceswindow.h
+++ b/src/osd/modules/debugger/qt/deviceswindow.h
@@ -73,8 +73,8 @@ public:
 
 	void buildFromQWidget(QWidget* widget);
 	void applyToQWidget(QWidget* widget);
-	void addToXmlDataNode(xml_data_node &node) const;
-	void recoverFromXmlNode(xml_data_node const &node);
+	void addToXmlDataNode(util::xml::data_node &node) const;
+	void recoverFromXmlNode(util::xml::data_node const &node);
 };
 
 
diff --git a/src/osd/modules/debugger/qt/logwindow.cpp b/src/osd/modules/debugger/qt/logwindow.cpp
index 8bd0d55..ecb8bf6 100644
--- a/src/osd/modules/debugger/qt/logwindow.cpp
+++ b/src/osd/modules/debugger/qt/logwindow.cpp
@@ -60,13 +60,13 @@ void LogWindowQtConfig::applyToQWidget(QWidget* widget)
 }
 
 
-void LogWindowQtConfig::addToXmlDataNode(xml_data_node &node) const
+void LogWindowQtConfig::addToXmlDataNode(util::xml::data_node &node) const
 {
 	WindowQtConfig::addToXmlDataNode(node);
 }
 
 
-void LogWindowQtConfig::recoverFromXmlNode(xml_data_node const &node)
+void LogWindowQtConfig::recoverFromXmlNode(util::xml::data_node const &node)
 {
 	WindowQtConfig::recoverFromXmlNode(node);
 }
diff --git a/src/osd/modules/debugger/qt/logwindow.h b/src/osd/modules/debugger/qt/logwindow.h
index dd1ebb4..53228ce 100644
--- a/src/osd/modules/debugger/qt/logwindow.h
+++ b/src/osd/modules/debugger/qt/logwindow.h
@@ -40,8 +40,8 @@ public:
 
 	void buildFromQWidget(QWidget* widget);
 	void applyToQWidget(QWidget* widget);
-	void addToXmlDataNode(xml_data_node &node) const;
-	void recoverFromXmlNode(xml_data_node const &node);
+	void addToXmlDataNode(util::xml::data_node &node) const;
+	void recoverFromXmlNode(util::xml::data_node const &node);
 };
 
 
diff --git a/src/osd/modules/debugger/qt/mainwindow.cpp b/src/osd/modules/debugger/qt/mainwindow.cpp
index 81be708..68a8fa0 100644
--- a/src/osd/modules/debugger/qt/mainwindow.cpp
+++ b/src/osd/modules/debugger/qt/mainwindow.cpp
@@ -526,7 +526,7 @@ void MainWindowQtConfig::applyToQWidget(QWidget* widget)
 }
 
 
-void MainWindowQtConfig::addToXmlDataNode(xml_data_node &node) const
+void MainWindowQtConfig::addToXmlDataNode(util::xml::data_node &node) const
 {
 	WindowQtConfig::addToXmlDataNode(node);
 	node.set_attribute_int("rightbar", m_rightBar);
@@ -534,7 +534,7 @@ void MainWindowQtConfig::addToXmlDataNode(xml_data_node &node) const
 }
 
 
-void MainWindowQtConfig::recoverFromXmlNode(xml_data_node const &node)
+void MainWindowQtConfig::recoverFromXmlNode(util::xml::data_node const &node)
 {
 	WindowQtConfig::recoverFromXmlNode(node);
 	const char* state = node.get_attribute_string("qtwindowstate", "");
diff --git a/src/osd/modules/debugger/qt/mainwindow.h b/src/osd/modules/debugger/qt/mainwindow.h
index 920ac43..95a4e53 100644
--- a/src/osd/modules/debugger/qt/mainwindow.h
+++ b/src/osd/modules/debugger/qt/mainwindow.h
@@ -199,8 +199,8 @@ public:
 
 	void buildFromQWidget(QWidget* widget);
 	void applyToQWidget(QWidget* widget);
-	void addToXmlDataNode(xml_data_node &node) const;
-	void recoverFromXmlNode(xml_data_node const &node);
+	void addToXmlDataNode(util::xml::data_node &node) const;
+	void recoverFromXmlNode(util::xml::data_node const &node);
 };
 
 
diff --git a/src/osd/modules/debugger/qt/memorywindow.cpp b/src/osd/modules/debugger/qt/memorywindow.cpp
index a15ce81..9875cc3 100644
--- a/src/osd/modules/debugger/qt/memorywindow.cpp
+++ b/src/osd/modules/debugger/qt/memorywindow.cpp
@@ -430,7 +430,7 @@ void MemoryWindowQtConfig::applyToQWidget(QWidget* widget)
 }
 
 
-void MemoryWindowQtConfig::addToXmlDataNode(xml_data_node &node) const
+void MemoryWindowQtConfig::addToXmlDataNode(util::xml::data_node &node) const
 {
 	WindowQtConfig::addToXmlDataNode(node);
 	node.set_attribute_int("memoryregion", m_memoryRegion);
@@ -440,7 +440,7 @@ void MemoryWindowQtConfig::addToXmlDataNode(xml_data_node &node) const
 }
 
 
-void MemoryWindowQtConfig::recoverFromXmlNode(xml_data_node const &node)
+void MemoryWindowQtConfig::recoverFromXmlNode(util::xml::data_node const &node)
 {
 	WindowQtConfig::recoverFromXmlNode(node);
 	m_memoryRegion = node.get_attribute_int("memoryregion", m_memoryRegion);
diff --git a/src/osd/modules/debugger/qt/memorywindow.h b/src/osd/modules/debugger/qt/memorywindow.h
index 42f81ac..ff0c974 100644
--- a/src/osd/modules/debugger/qt/memorywindow.h
+++ b/src/osd/modules/debugger/qt/memorywindow.h
@@ -91,8 +91,8 @@ public:
 
 	void buildFromQWidget(QWidget* widget);
 	void applyToQWidget(QWidget* widget);
-	void addToXmlDataNode(xml_data_node &node) const;
-	void recoverFromXmlNode(xml_data_node const &node);
+	void addToXmlDataNode(util::xml::data_node &node) const;
+	void recoverFromXmlNode(util::xml::data_node const &node);
 };
 
 
diff --git a/src/osd/modules/debugger/qt/windowqt.cpp b/src/osd/modules/debugger/qt/windowqt.cpp
index 09709ad..c908ac5 100644
--- a/src/osd/modules/debugger/qt/windowqt.cpp
+++ b/src/osd/modules/debugger/qt/windowqt.cpp
@@ -257,7 +257,7 @@ void WindowQtConfig::applyToQWidget(QWidget* widget)
 }
 
 
-void WindowQtConfig::addToXmlDataNode(xml_data_node &node) const
+void WindowQtConfig::addToXmlDataNode(util::xml::data_node &node) const
 {
 	node.set_attribute_int("type", m_type);
 	node.set_attribute_int("position_x", m_position.x());
@@ -267,7 +267,7 @@ void WindowQtConfig::addToXmlDataNode(xml_data_node &node) const
 }
 
 
-void WindowQtConfig::recoverFromXmlNode(xml_data_node const &node)
+void WindowQtConfig::recoverFromXmlNode(util::xml::data_node const &node)
 {
 	m_size.setX(node.get_attribute_int("size_x", m_size.x()));
 	m_size.setY(node.get_attribute_int("size_y", m_size.y()));
diff --git a/src/osd/modules/debugger/qt/windowqt.h b/src/osd/modules/debugger/qt/windowqt.h
index 6f9701f..28b3039 100644
--- a/src/osd/modules/debugger/qt/windowqt.h
+++ b/src/osd/modules/debugger/qt/windowqt.h
@@ -92,8 +92,8 @@ public:
 
 	virtual void buildFromQWidget(QWidget* widget);
 	virtual void applyToQWidget(QWidget* widget);
-	virtual void addToXmlDataNode(xml_data_node &node) const;
-	virtual void recoverFromXmlNode(xml_data_node const &node);
+	virtual void addToXmlDataNode(util::xml::data_node &node) const;
+	virtual void recoverFromXmlNode(util::xml::data_node const &node);
 };
 
 
diff --git a/src/osd/modules/debugger/win/editwininfo.cpp b/src/osd/modules/debugger/win/editwininfo.cpp
index 6dc4954..96b424a 100644
--- a/src/osd/modules/debugger/win/editwininfo.cpp
+++ b/src/osd/modules/debugger/win/editwininfo.cpp
@@ -16,9 +16,15 @@
 #include "winutil.h"
 
 
-// edit box styles
-#define EDIT_BOX_STYLE      WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL
-#define EDIT_BOX_STYLE_EX   0
+namespace {
+
+constexpr DWORD EDIT_BOX_STYLE      = WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL;
+constexpr DWORD EDIT_BOX_STYLE_EX   = 0;
+
+constexpr int   MAX_EDIT_STRING     = 256;
+constexpr int   HISTORY_LENGTH      = 20;
+
+} // anonymous namespace
 
 
 editwin_info::editwin_info(debugger_windows_interface &debugger, bool is_main_console, LPCSTR title, WNDPROC handler) :
@@ -26,7 +32,7 @@ editwin_info::editwin_info(debugger_windows_interface &debugger, bool is_main_co
 	m_editwnd(nullptr),
 	m_edit_defstr(),
 	m_original_editproc(nullptr),
-	m_history_count(0),
+	m_history(),
 	m_last_history(0)
 {
 	if (window() == nullptr)
@@ -35,11 +41,11 @@ editwin_info::editwin_info(debugger_windows_interface &debugger, bool is_main_co
 	// create an edit box and override its key handling
 	m_editwnd = CreateWindowEx(EDIT_BOX_STYLE_EX, TEXT("EDIT"), nullptr, EDIT_BOX_STYLE,
 			0, 0, 100, 100, window(), nullptr, GetModuleHandleUni(), nullptr);
-	m_original_editproc = (WNDPROC)(uintptr_t)GetWindowLongPtr(m_editwnd, GWLP_WNDPROC);
-	SetWindowLongPtr(m_editwnd, GWLP_USERDATA, (LONG_PTR)this);
-	SetWindowLongPtr(m_editwnd, GWLP_WNDPROC, (LONG_PTR)&editwin_info::static_edit_proc);
-	SendMessage(m_editwnd, WM_SETFONT, (WPARAM)metrics().debug_font(), (LPARAM)FALSE);
-	SendMessage(m_editwnd, EM_LIMITTEXT, (WPARAM)MAX_EDIT_STRING, (LPARAM)0);
+	m_original_editproc = WNDPROC(uintptr_t(GetWindowLongPtr(m_editwnd, GWLP_WNDPROC)));
+	SetWindowLongPtr(m_editwnd, GWLP_USERDATA, LONG_PTR(this));
+	SetWindowLongPtr(m_editwnd, GWLP_WNDPROC, LONG_PTR(&editwin_info::static_edit_proc));
+	SendMessage(m_editwnd, WM_SETFONT, WPARAM(metrics().debug_font()), LPARAM(FALSE));
+	SendMessage(m_editwnd, EM_LIMITTEXT, WPARAM(MAX_EDIT_STRING), LPARAM(0));
 	set_editwnd_text("");
 }
 
@@ -80,13 +86,13 @@ void editwin_info::set_editwnd_bounds(RECT const &bounds)
 void editwin_info::set_editwnd_text(char const *text)
 {
 	auto tc_buffer = osd::text::to_tstring(text);
-	SendMessage(m_editwnd, WM_SETTEXT, (WPARAM)0, (LPARAM)tc_buffer.c_str());
+	SendMessage(m_editwnd, WM_SETTEXT, WPARAM(0), LPARAM(tc_buffer.c_str()));
 }
 
 
 void editwin_info::editwnd_select_all()
 {
-	SendMessage(m_editwnd, EM_SETSEL, (WPARAM)0, (LPARAM)-1);
+	SendMessage(m_editwnd, EM_SETSEL, WPARAM(0), LPARAM(-1));
 }
 
 
@@ -100,8 +106,6 @@ void editwin_info::draw_contents(HDC dc)
 
 LRESULT editwin_info::edit_proc(UINT message, WPARAM wparam, LPARAM lparam)
 {
-	TCHAR buffer[MAX_EDIT_STRING];
-
 	// handle a few messages
 	switch (message)
 	{
@@ -114,23 +118,28 @@ LRESULT editwin_info::edit_proc(UINT message, WPARAM wparam, LPARAM lparam)
 		switch (wparam)
 		{
 		case VK_UP:
-			if (m_last_history < (m_history_count - 1))
+			if (!m_history.empty())
+			{
 				m_last_history++;
-			else
-				m_last_history = 0;
-			SendMessage(m_editwnd, WM_SETTEXT, (WPARAM)0, (LPARAM)&m_history[m_last_history][0]);
-			SendMessage(m_editwnd, EM_SETSEL, (WPARAM)MAX_EDIT_STRING, (LPARAM)MAX_EDIT_STRING);
+				if (m_last_history >= m_history.size())
+					m_last_history = 0;
+				auto const &entry(m_history[m_last_history]);
+				SendMessage(m_editwnd, WM_SETTEXT, WPARAM(0), LPARAM(entry.c_str()));
+				SendMessage(m_editwnd, EM_SETSEL, WPARAM(entry.length()), LPARAM(entry.length()));
+			}
 			break;
 
 		case VK_DOWN:
-			if (m_last_history > 0)
-				m_last_history--;
-			else if (m_history_count > 0)
-				m_last_history = m_history_count - 1;
-			else
-				m_last_history = 0;
-			SendMessage(m_editwnd, WM_SETTEXT, (WPARAM)0, (LPARAM)&m_history[m_last_history][0]);
-			SendMessage(m_editwnd, EM_SETSEL, (WPARAM)MAX_EDIT_STRING, (LPARAM)MAX_EDIT_STRING);
+			if (!m_history.empty())
+			{
+				if (m_last_history > 0)
+					m_last_history--;
+				else
+					m_last_history = m_history.size() - 1;
+				auto const &entry(m_history[m_last_history]);
+				SendMessage(m_editwnd, WM_SETTEXT, WPARAM(0), LPARAM(entry.c_str()));
+				SendMessage(m_editwnd, EM_SETSEL, WPARAM(entry.length()), LPARAM(entry.length()));
+			}
 			break;
 
 		case VK_PRIOR:
@@ -168,35 +177,36 @@ LRESULT editwin_info::edit_proc(UINT message, WPARAM wparam, LPARAM lparam)
 		{
 			if (waiting_for_debugger() || !seq_pressed())
 			{
+				TCHAR buffer[MAX_EDIT_STRING];
+
 				switch (wparam)
 				{
-				case 13:
+				case 13: // carriage return
 					{
 						// fetch the text
-						SendMessage(m_editwnd, WM_GETTEXT, (WPARAM)ARRAY_LENGTH(buffer), (LPARAM)buffer);
+						SendMessage(m_editwnd, WM_GETTEXT, WPARAM(ARRAY_LENGTH(buffer)), LPARAM(buffer));
 
 						// add to the history if it's not a repeat of the last one
-						if (buffer[0] != 0 && _tcscmp(buffer, &m_history[0][0]))
+						if (buffer[0] && (m_history.empty() || _tcscmp(buffer, m_history[0].c_str())))
 						{
-							memmove(&m_history[1][0], &m_history[0][0], (HISTORY_LENGTH - 1) * MAX_EDIT_STRING * sizeof(TCHAR));
-							_tcscpy(&m_history[0][0], buffer);
-							if (m_history_count < HISTORY_LENGTH)
-								m_history_count++;
+							while (m_history.size() >= HISTORY_LENGTH)
+								m_history.pop_back();
+							m_history.emplace_front(buffer);
 						}
-						m_last_history = m_history_count - 1;
+						m_last_history = m_history.size() - 1;
 
 						// process
 						{
 							auto utf8_buffer = osd::text::from_tstring(buffer);
 							process_string(utf8_buffer.c_str());
 						}
-						break;
 					}
+					break;
 
-				case 27:
+				case 27: // escape
 					{
 						// fetch the text
-						SendMessage(m_editwnd, WM_GETTEXT, (WPARAM)sizeof(buffer), (LPARAM)buffer);
+						SendMessage(m_editwnd, WM_GETTEXT, WPARAM(sizeof(buffer)), LPARAM(buffer));
 
 						// if it's not empty, clear the text
 						if (_tcslen(buffer) > 0)
@@ -205,8 +215,8 @@ LRESULT editwin_info::edit_proc(UINT message, WPARAM wparam, LPARAM lparam)
 							set_editwnd_text(m_edit_defstr.c_str());
 							editwnd_select_all();
 						}
-						break;
 					}
+					break;
 
 				default:
 					return CallWindowProc(m_original_editproc, m_editwnd, message, wparam, lparam);
@@ -226,7 +236,7 @@ LRESULT editwin_info::edit_proc(UINT message, WPARAM wparam, LPARAM lparam)
 
 LRESULT CALLBACK editwin_info::static_edit_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
 {
-	editwin_info *const info = (editwin_info *)(uintptr_t)GetWindowLongPtr(wnd, GWLP_USERDATA);
+	editwin_info *const info = (editwin_info *)uintptr_t(GetWindowLongPtr(wnd, GWLP_USERDATA));
 	assert(info->m_editwnd == wnd);
 	return info->edit_proc(message, wparam, lparam);
 }
diff --git a/src/osd/modules/debugger/win/editwininfo.h b/src/osd/modules/debugger/win/editwininfo.h
index 5da8059..4a1e423 100644
--- a/src/osd/modules/debugger/win/editwininfo.h
+++ b/src/osd/modules/debugger/win/editwininfo.h
@@ -6,13 +6,16 @@
 //
 //============================================================
 
-#ifndef __DEBUG_WIN_EDIT_WIN_INFO_H__
-#define __DEBUG_WIN_EDIT_WIN_INFO_H__
+#ifndef MAME_DEBUG_WIN_EDIT_WIN_INFO_H
+#define MAME_DEBUG_WIN_EDIT_WIN_INFO_H
 
 #include "debugwin.h"
 
 #include "debugwininfo.h"
 
+#include <deque>
+#include <string>
+
 
 class editwin_info : public debugwin_info
 {
@@ -25,8 +28,8 @@ public:
 	virtual bool set_default_focus() override;
 
 protected:
-	static DWORD const  COMBO_BOX_STYLE     = WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_VSCROLL;
-	static DWORD const  COMBO_BOX_STYLE_EX  = 0;
+	constexpr static DWORD  COMBO_BOX_STYLE     = WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_VSCROLL;
+	constexpr static DWORD  COMBO_BOX_STYLE_EX  = 0;
 
 	void set_editwnd_bounds(RECT const &bounds);
 	void set_editwnd_text(char const *text);
@@ -36,21 +39,19 @@ protected:
 	virtual void draw_contents(HDC dc) override;
 
 private:
+	typedef std::deque<std::basic_string<TCHAR> > history_deque;
+
 	virtual void process_string(char const *string) = 0;
 
 	LRESULT edit_proc(UINT message, WPARAM wparam, LPARAM lparam);
 
 	static LRESULT CALLBACK static_edit_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam);
 
-	static int const    MAX_EDIT_STRING = 256;
-	static int const    HISTORY_LENGTH = 20;
-
-	HWND                m_editwnd;
-	std::string         m_edit_defstr;
-	WNDPROC             m_original_editproc;
-	TCHAR               m_history[HISTORY_LENGTH][MAX_EDIT_STRING];
-	int                 m_history_count;
-	int                 m_last_history;
+	HWND                    m_editwnd;
+	std::string             m_edit_defstr;
+	WNDPROC                 m_original_editproc;
+	history_deque           m_history;
+	int                     m_last_history;
 };
 
 #endif
diff --git a/src/osd/modules/font/font_dwrite.cpp b/src/osd/modules/font/font_dwrite.cpp
index b408508..7323167 100644
--- a/src/osd/modules/font/font_dwrite.cpp
+++ b/src/osd/modules/font/font_dwrite.cpp
@@ -66,11 +66,6 @@ static const float POINTS_PER_DIP = (3.0f / 4.0f);
 #define HR_RET0( CALL ) HR_RET(CALL, 0)
 #define HR_RET1( CALL ) HR_RET(CALL, 1)
 
-// Typedefs for dynamically loaded functions
-typedef HRESULT (WINAPI *d2d_create_factory_fn)(D2D1_FACTORY_TYPE, REFIID, const D2D1_FACTORY_OPTIONS *, void **);
-typedef HRESULT (WINAPI *dwrite_create_factory_fn)(DWRITE_FACTORY_TYPE, REFIID, IUnknown **);
-typedef int (WINAPI *get_user_default_locale_name)(LPWSTR, int);
-
 // Debugging functions
 #ifdef DWRITE_DEBUGGING
 
@@ -86,17 +81,16 @@ HRESULT SaveBitmap(IWICBitmap* bitmap, GUID pixelFormat, const WCHAR *filename)
 	ComPtr<IDWriteFactory> dwriteFactory;
 	ComPtr<IWICImagingFactory> wicFactory;
 
-	osd::dynamic_module::ptr d2d1_dll = osd::dynamic_module::open({ "d2d1.dll" });
-	osd::dynamic_module::ptr dwrite_dll = osd::dynamic_module::open({ "dwrite.dll" });
-
-	d2d_create_factory_fn pfn_D2D1CreateFactory = d2d1_dll->bind<d2d_create_factory_fn>("D2D1CreateFactory");
-	dwrite_create_factory_fn pfn_DWriteCreateFactory = dwrite_dll->bind<dwrite_create_factory_fn>("DWriteCreateFactory");
+	OSD_DYNAMIC_API(dwrite, "dwrite.dll");
+	OSD_DYNAMIC_API(d2d1, "d2d1.dll");
+	OSD_DYNAMIC_API_FN(dwrite, HRESULT, WINAPI, DWriteCreateFactory, DWRITE_FACTORY_TYPE, REFIID, IUnknown **);
+	OSD_DYNAMIC_API_FN(d2d1, HRESULT, WINAPI, D2D1CreateFactory, D2D1_FACTORY_TYPE, REFIID, const D2D1_FACTORY_OPTIONS *, void **);
 
-	if (!pfn_D2D1CreateFactory || !pfn_DWriteCreateFactory)
+	if (!OSD_DYNAMIC_API_TEST(D2D1CreateFactory) || !OSD_DYNAMIC_API_TEST(DWriteCreateFactory))
 		return ERROR_DLL_NOT_FOUND;
 
 	// Create a Direct2D factory
-	HR_RETHR((*pfn_D2D1CreateFactory)(
+	HR_RETHR(OSD_DYNAMIC_CALL(D2D1CreateFactory,
 		D2D1_FACTORY_TYPE_SINGLE_THREADED,
 		__uuidof(ID2D1Factory1),
 		nullptr,
@@ -106,7 +100,7 @@ HRESULT SaveBitmap(IWICBitmap* bitmap, GUID pixelFormat, const WCHAR *filename)
 	CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
 
 	// Create a DirectWrite factory.
-	HR_RETHR((*pfn_DWriteCreateFactory)(
+	HR_RETHR(OSD_DYNAMIC_CALL(DWriteCreateFactory,
 		DWRITE_FACTORY_TYPE_SHARED,
 		__uuidof(IDWriteFactory),
 		reinterpret_cast<IUnknown **>(dwriteFactory.GetAddressOf())));
@@ -653,12 +647,12 @@ private:
 class font_dwrite : public osd_module, public font_module
 {
 private:
-	osd::dynamic_module::ptr     m_d2d1_dll;
-	osd::dynamic_module::ptr     m_dwrite_dll;
-	osd::dynamic_module::ptr     m_kernel32_dll;
-	d2d_create_factory_fn        m_pfnD2D1CreateFactory;
-	dwrite_create_factory_fn     m_pfnDWriteCreateFactory;
-	get_user_default_locale_name m_pfnGetUserDefaultLocaleName;
+	OSD_DYNAMIC_API(dwrite, "dwrite.dll");
+	OSD_DYNAMIC_API(d2d1, "d2d1.dll");
+	OSD_DYNAMIC_API(locale, "kernel32.dll");
+	OSD_DYNAMIC_API_FN(dwrite, HRESULT, WINAPI, DWriteCreateFactory, DWRITE_FACTORY_TYPE, REFIID, IUnknown **);
+	OSD_DYNAMIC_API_FN(d2d1, HRESULT, WINAPI, D2D1CreateFactory, D2D1_FACTORY_TYPE, REFIID, const D2D1_FACTORY_OPTIONS *, void **);
+	OSD_DYNAMIC_API_FN(locale, int, WINAPI, GetUserDefaultLocaleName, LPWSTR, int);
 	ComPtr<ID2D1Factory>         m_d2dfactory;
 	ComPtr<IDWriteFactory>       m_dwriteFactory;
 	ComPtr<IWICImagingFactory>   m_wicFactory;
@@ -667,9 +661,6 @@ public:
 	font_dwrite() :
 		osd_module(OSD_FONT_PROVIDER, "dwrite"),
 		font_module(),
-		m_pfnD2D1CreateFactory(nullptr),
-		m_pfnDWriteCreateFactory(nullptr),
-		m_pfnGetUserDefaultLocaleName(nullptr),
 		m_d2dfactory(nullptr),
 		m_dwriteFactory(nullptr),
 		m_wicFactory(nullptr)
@@ -678,14 +669,8 @@ public:
 
 	virtual bool probe() override
 	{
-		m_d2d1_dll = osd::dynamic_module::open({ "d2d1.dll" });
-		m_dwrite_dll = osd::dynamic_module::open({ "dwrite.dll" });
-
-		m_pfnD2D1CreateFactory = m_d2d1_dll->bind<d2d_create_factory_fn>("D2D1CreateFactory");
-		m_pfnDWriteCreateFactory = m_dwrite_dll->bind<dwrite_create_factory_fn>("DWriteCreateFactory");
-
 		// This module is available if it can load the expected API Functions
-		if (!m_pfnD2D1CreateFactory || !m_pfnDWriteCreateFactory)
+		if (!OSD_DYNAMIC_API_TEST(D2D1CreateFactory) || !OSD_DYNAMIC_API_TEST(DWriteCreateFactory))
 			return false;
 
 		return true;
@@ -698,21 +683,16 @@ public:
 		osd_printf_verbose("FontProvider: Initializing DirectWrite\n");
 
 		// Make sure we can initialize our api functions
-		if (!m_pfnD2D1CreateFactory || !m_pfnDWriteCreateFactory)
+		if (!OSD_DYNAMIC_API_TEST(D2D1CreateFactory) || !OSD_DYNAMIC_API_TEST(DWriteCreateFactory))
 		{
 			osd_printf_error("ERROR: FontProvider: Failed to load DirectWrite functions.\n");
 			return -1;
 		}
 
-		// Init our kernel32 dynamic functions
-		m_kernel32_dll = osd::dynamic_module::open({ "Kernel32.dll" });
-		assert(m_kernel32_dll != nullptr);
-
-		// Attempt to map this function. It only exists on Vista+, so we don't fail if it can't be mapped
-		m_pfnGetUserDefaultLocaleName = m_kernel32_dll->bind<get_user_default_locale_name>("GetUserDefaultLocaleName");
+		assert(OSD_DYNAMIC_API_TEST(GetUserDefaultLocaleName));
 
 		// Create a Direct2D factory.
-		HR_RET1((*m_pfnD2D1CreateFactory)(
+		HR_RET1(OSD_DYNAMIC_CALL(D2D1CreateFactory,
 			D2D1_FACTORY_TYPE_SINGLE_THREADED,
 			__uuidof(ID2D1Factory),
 			nullptr,
@@ -722,7 +702,7 @@ public:
 		CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
 
 		// Create a DirectWrite factory.
-		HR_RET1((*m_pfnDWriteCreateFactory)(
+		HR_RET1(OSD_DYNAMIC_CALL(DWriteCreateFactory,
 			DWRITE_FACTORY_TYPE_SHARED,
 			__uuidof(IDWriteFactory),
 			reinterpret_cast<IUnknown **>(m_dwriteFactory.GetAddressOf())));
@@ -811,10 +791,10 @@ private:
 
 		// Get the default locale for this user if possible.
 		// GetUserDefaultLocaleName doesn't exist on XP, so don't assume.
-		if (m_pfnGetUserDefaultLocaleName)
+		if (OSD_DYNAMIC_API_TEST(GetUserDefaultLocaleName))
 		{
 			wchar_t name_buffer[LOCALE_NAME_MAX_LENGTH];
-			int len = m_pfnGetUserDefaultLocaleName(name_buffer, LOCALE_NAME_MAX_LENGTH);
+			int len = OSD_DYNAMIC_CALL(GetUserDefaultLocaleName, name_buffer, LOCALE_NAME_MAX_LENGTH);
 			if (len != 0)
 				locale_name = name_buffer;
 		}
diff --git a/src/osd/modules/lib/osdlib.h b/src/osd/modules/lib/osdlib.h
index 7580c92..afcc522 100644
--- a/src/osd/modules/lib/osdlib.h
+++ b/src/osd/modules/lib/osdlib.h
@@ -19,6 +19,7 @@
 #include <string>
 #include <type_traits>
 #include <vector>
+#include <memory>
 
 /*-----------------------------------------------------------------------------
     osd_process_kill: kill the current process
@@ -98,4 +99,29 @@ protected:
 
 } // namespace osd
 
+//=========================================================================================================
+// Dynamic API helpers. Useful in creating a class members that expose dynamically bound API functions.
+//
+// OSD_DYNAMIC_API(dxgi, "dxgi.dll")
+// DYNAMIC_API_FN(dxgi, DWORD, WINAPI, CreateDXGIFactory1, REFIID, void**)
+//
+// Calling then looks like: DYNAMIC_CALL(CreateDXGIFactory1, p1, p2, etc)
+//=========================================================================================================
+
+#if !defined(OSD_UWP)
+
+#define OSD_DYNAMIC_API(apiname, ...) osd::dynamic_module::ptr m_##apiname##module = osd::dynamic_module::open( { __VA_ARGS__ } )
+#define OSD_DYNAMIC_API_FN(apiname, ret, conv, fname, ...) ret(conv *m_##fname##_pfn)( __VA_ARGS__ ) = m_##apiname##module->bind<ret(conv *)( __VA_ARGS__ )>(#fname)
+#define OSD_DYNAMIC_CALL(fname, ...) (*m_##fname##_pfn) ( __VA_ARGS__ )
+#define OSD_DYNAMIC_API_TEST(fname) (m_##fname##_pfn != nullptr)
+
+#else
+
+#define OSD_DYNAMIC_API(apiname, ...)
+#define OSD_DYNAMIC_API_FN(apiname, ret, conv, fname, ...)
+#define OSD_DYNAMIC_CALL(fname, ...) fname( __VA_ARGS__ )
+#define OSD_DYNAMIC_API_TEST(fname) (true)
+
+#endif
+
 #endif  /* __OSDLIB__ */
diff --git a/src/osd/modules/lib/osdlib_uwp.cpp b/src/osd/modules/lib/osdlib_uwp.cpp
index 27c0ac4..170f964 100644
--- a/src/osd/modules/lib/osdlib_uwp.cpp
+++ b/src/osd/modules/lib/osdlib_uwp.cpp
@@ -176,215 +176,3 @@ char *osd_get_clipboard_text(void)
 
 	return result;
 }
-
-//============================================================
-//  osd_dynamic_bind
-//============================================================
-// for Windows Store universal applications
-// This needs to change ASAP as it won't be allowed in the store
-typedef HMODULE __stdcall t_LLA(const char *);
-typedef FARPROC __stdcall t_GPA(HMODULE H, const char *);
-
-PIMAGE_NT_HEADERS WINAPI ImageNtHeader(PVOID Base)
-{
-	return (PIMAGE_NT_HEADERS)
-		((LPBYTE)Base + ((PIMAGE_DOS_HEADER)Base)->e_lfanew);
-}
-
-PIMAGE_SECTION_HEADER WINAPI RtlImageRvaToSection(const IMAGE_NT_HEADERS *nt,
-	HMODULE module, DWORD_PTR rva)
-{
-	int i;
-	const IMAGE_SECTION_HEADER *sec;
-
-	sec = (const IMAGE_SECTION_HEADER*)((const char*)&nt->OptionalHeader +
-		nt->FileHeader.SizeOfOptionalHeader);
-	for (i = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)
-	{
-		if ((sec->VirtualAddress <= rva) && (sec->VirtualAddress + sec->SizeOfRawData > rva))
-			return (PIMAGE_SECTION_HEADER)sec;
-	}
-	return NULL;
-}
-
-PVOID WINAPI RtlImageRvaToVa(const IMAGE_NT_HEADERS *nt, HMODULE module,
-	DWORD_PTR rva, IMAGE_SECTION_HEADER **section)
-{
-	IMAGE_SECTION_HEADER *sec;
-
-	if (section && *section)  /* try this section first */
-	{
-		sec = *section;
-		if ((sec->VirtualAddress <= rva) && (sec->VirtualAddress + sec->SizeOfRawData > rva))
-			goto found;
-	}
-	if (!(sec = RtlImageRvaToSection(nt, module, rva))) return NULL;
-found:
-	if (section) *section = sec;
-	return (char *)module + sec->PointerToRawData + (rva - sec->VirtualAddress);
-}
-
-PVOID WINAPI ImageDirectoryEntryToDataEx(PVOID base, BOOLEAN image, USHORT dir, PULONG size, PIMAGE_SECTION_HEADER *section)
-{
-	const IMAGE_NT_HEADERS *nt;
-	DWORD_PTR addr;
-
-	*size = 0;
-	if (section) *section = NULL;
-
-	if (!(nt = ImageNtHeader(base))) return NULL;
-	if (dir >= nt->OptionalHeader.NumberOfRvaAndSizes) return NULL;
-	if (!(addr = nt->OptionalHeader.DataDirectory[dir].VirtualAddress)) return NULL;
-
-	*size = nt->OptionalHeader.DataDirectory[dir].Size;
-	if (image || addr < nt->OptionalHeader.SizeOfHeaders) return (char *)base + addr;
-
-	return RtlImageRvaToVa(nt, (HMODULE)base, addr, section);
-}
-
-// == Windows API GetProcAddress
-void *PeGetProcAddressA(void *Base, LPCSTR Name)
-{
-	DWORD Tmp;
-
-	IMAGE_NT_HEADERS *NT = ImageNtHeader(Base);
-	IMAGE_EXPORT_DIRECTORY *Exp = (IMAGE_EXPORT_DIRECTORY*)ImageDirectoryEntryToDataEx(Base, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &Tmp, 0);
-	if (Exp == 0 || Exp->NumberOfFunctions == 0)
-	{
-		SetLastError(ERROR_NOT_FOUND);
-		return 0;
-	}
-
-	DWORD *Names = (DWORD*)(Exp->AddressOfNames + (DWORD_PTR)Base);
-	WORD *Ordinals = (WORD*)(Exp->AddressOfNameOrdinals + (DWORD_PTR)Base);
-	DWORD *Functions = (DWORD*)(Exp->AddressOfFunctions + (DWORD_PTR)Base);
-
-	FARPROC Ret = 0;
-
-	if ((DWORD_PTR)Name<65536)
-	{
-		if ((DWORD_PTR)Name - Exp->Base<Exp->NumberOfFunctions)
-			Ret = (FARPROC)(Functions[(DWORD_PTR)Name - Exp->Base] + (DWORD_PTR)Base);
-	}
-	else
-	{
-		for (DWORD i = 0; i<Exp->NumberOfNames && Ret == 0; i++)
-		{
-			char *Func = (char*)(Names[i] + std::uintptr_t(Base));
-			if (Func && strcmp(Func, Name) == 0)
-				Ret = (FARPROC)(Functions[Ordinals[i]] + std::uintptr_t(Base));
-		}
-	}
-
-	if (Ret)
-	{
-		std::uintptr_t ExpStart = NT->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + std::uintptr_t(Base);
-		std::uintptr_t ExpSize = NT->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
-		if (std::uintptr_t(Ret) >= ExpStart && std::uintptr_t(Ret) <= ExpStart + ExpSize)
-		{
-			// Forwarder
-			return 0;
-		}
-		return Ret;
-	}
-
-	return 0;
-}
-
-t_LLA* g_LoadLibraryA = 0;
-t_GPA* g_GetProcAddressA = 0;
-
-void find_load_exports()
-{
-	char *Tmp = (char*)GetTickCount64;
-	Tmp = (char*)((~0xFFF)&(DWORD_PTR)Tmp);
-
-	while (Tmp)
-	{
-		__try
-		{
-			if (Tmp[0] == 'M' && Tmp[1] == 'Z')
-				break;
-		}
-		__except (EXCEPTION_EXECUTE_HANDLER)
-		{
-		}
-		Tmp -= 0x1000;
-	}
-
-	if (Tmp == 0)
-		return;
-
-	g_LoadLibraryA = (t_LLA*)PeGetProcAddressA(Tmp, "LoadLibraryA");
-	g_GetProcAddressA = (t_GPA*)PeGetProcAddressA(Tmp, "GetProcAddress");
-}
-
-#define load_library(filename) g_LoadLibraryA(osd::text::from_wstring(filename).c_str())
-#define get_proc_address(mod, proc) g_GetProcAddressA(mod, proc)
-
-
-
-namespace osd {
-class dynamic_module_win32_impl : public dynamic_module
-{
-public:
-	dynamic_module_win32_impl(std::vector<std::string> &libraries)
-		: m_module(nullptr)
-	{
-		m_libraries = libraries;
-		find_load_exports();
-	}
-
-	virtual ~dynamic_module_win32_impl() override
-	{
-		if (m_module != nullptr)
-			FreeLibrary(m_module);
-	};
-
-protected:
-	virtual generic_fptr_t get_symbol_address(char const *symbol) override
-	{
-		/*
-		 * given a list of libraries, if a first symbol is successfully loaded from
-		 * one of them, all additional symbols will be loaded from the same library
-		 */
-		if (m_module)
-		{
-			return reinterpret_cast<generic_fptr_t>(GetProcAddress(m_module, symbol));
-		}
-
-		for (auto const &library : m_libraries)
-		{
-			osd::text::tstring tempstr = osd::text::to_tstring(library);
-			HMODULE module = load_library(tempstr.c_str());
-
-			if (module != nullptr)
-			{
-				generic_fptr_t function = reinterpret_cast<generic_fptr_t>(GetProcAddress(module, symbol));
-
-				if (function != nullptr)
-				{
-					m_module = module;
-					return function;
-				}
-				else
-				{
-					FreeLibrary(module);
-				}
-			}
-		}
-
-		return nullptr;
-	}
-
-private:
-	std::vector<std::string> m_libraries;
-	HMODULE                  m_module;
-};
-
-dynamic_module::ptr dynamic_module::open(std::vector<std::string> &&names)
-{
-	return std::make_unique<dynamic_module_win32_impl>(names);
-}
-
-} // namespace osd
diff --git a/src/osd/modules/monitor/monitor_dxgi.cpp b/src/osd/modules/monitor/monitor_dxgi.cpp
index 3336092..27380ed 100644
--- a/src/osd/modules/monitor/monitor_dxgi.cpp
+++ b/src/osd/modules/monitor/monitor_dxgi.cpp
@@ -54,26 +54,21 @@ public:
 	}
 };
 
-typedef DWORD(WINAPI *dxgi_create_factory_fn)(REFIID, void**);
 
 class dxgi_monitor_module : public monitor_module_base
 {
 private:
-	osd::dynamic_module::ptr m_dxgi_module;
-	dxgi_create_factory_fn   m_create_factory_fn;
-
+	OSD_DYNAMIC_API(dxgi, "dxgi.dll");
+	OSD_DYNAMIC_API_FN(dxgi, DWORD, WINAPI, CreateDXGIFactory1, REFIID, void**);
 public:
 	dxgi_monitor_module()
-		: monitor_module_base(OSD_MONITOR_PROVIDER, "dxgi"),
-			m_dxgi_module(osd::dynamic_module::open({"dxgi.dll"})),
-			m_create_factory_fn(nullptr)
+		: monitor_module_base(OSD_MONITOR_PROVIDER, "dxgi")
 	{
 	}
 
 	bool probe() override
 	{
-		m_create_factory_fn = m_dxgi_module->bind<dxgi_create_factory_fn>("CreateDXGIFactory1");
-		if (m_create_factory_fn == nullptr)
+		if(!OSD_DYNAMIC_API_TEST(CreateDXGIFactory1))
 			return false;
 
 		return true;
@@ -133,7 +128,7 @@ protected:
 		ComPtr<IDXGIFactory2> factory;
 		ComPtr<IDXGIAdapter> adapter;
 
-		result = m_create_factory_fn(__uuidof(IDXGIFactory2), reinterpret_cast<void**>(factory.GetAddressOf()));
+		result = OSD_DYNAMIC_CALL(CreateDXGIFactory1, __uuidof(IDXGIFactory2), reinterpret_cast<void**>(factory.GetAddressOf()));
 		if (result != ERROR_SUCCESS)
 		{
 			osd_printf_error("CreateDXGIFactory1 failed with error 0x%x\n", static_cast<unsigned int>(result));
diff --git a/src/osd/modules/render/bgfx/shaders/makefile b/src/osd/modules/render/bgfx/shaders/makefile
index 792ef56..1ca4547 100644
--- a/src/osd/modules/render/bgfx/shaders/makefile
+++ b/src/osd/modules/render/bgfx/shaders/makefile
@@ -32,5 +32,5 @@ endif
 	@make -s --no-print-directory TARGET=3 clean all
 	@make -s --no-print-directory TARGET=4 clean all
 	@make -s --no-print-directory TARGET=5 clean all
-	
+
 .PHONY: main rebuild $(SUBDIRS)
diff --git a/src/osd/modules/render/d3d/d3dhlsl.cpp b/src/osd/modules/render/d3d/d3dhlsl.cpp
index dff6082..a6cfad8 100644
--- a/src/osd/modules/render/d3d/d3dhlsl.cpp
+++ b/src/osd/modules/render/d3d/d3dhlsl.cpp
@@ -164,14 +164,15 @@ private:
 
 shaders::shaders() :
 	d3dintf(nullptr), machine(nullptr), d3d(nullptr), post_fx_enable(false), oversampling_enable(false),
-	num_screens(0), curr_screen(0), shadow_texture(nullptr), options(nullptr), black_surface(nullptr),
-	black_texture(nullptr), recording_movie(false), render_snap(false), snap_copy_target(nullptr),
-	snap_copy_texture(nullptr), snap_target(nullptr), snap_texture(nullptr), snap_width(0), snap_height(0),
-	initialized(false), backbuffer(nullptr), curr_effect(nullptr), default_effect(nullptr),
-	prescale_effect(nullptr), post_effect(nullptr), distortion_effect(nullptr), focus_effect(nullptr),
-	phosphor_effect(nullptr), deconverge_effect(nullptr), color_effect(nullptr), ntsc_effect(nullptr),
-	bloom_effect(nullptr), downsample_effect(nullptr), vector_effect(nullptr), curr_texture(nullptr),
-	curr_render_target(nullptr), curr_poly(nullptr), d3dx_create_effect_from_file_ptr(nullptr)
+	num_screens(0), curr_screen(0), acc_t(0), delta_t(0), shadow_texture(nullptr), options(nullptr),
+	black_surface(nullptr), black_texture(nullptr), recording_movie(false), render_snap(false),
+	snap_copy_target(nullptr), snap_copy_texture(nullptr), snap_target(nullptr), snap_texture(nullptr),
+	snap_width(0), snap_height(0), initialized(false), backbuffer(nullptr), curr_effect(nullptr),
+	default_effect(nullptr), prescale_effect(nullptr), post_effect(nullptr), distortion_effect(nullptr),
+	focus_effect(nullptr), phosphor_effect(nullptr), deconverge_effect(nullptr), color_effect(nullptr),
+	ntsc_effect(nullptr), bloom_effect(nullptr), downsample_effect(nullptr), vector_effect(nullptr),
+	curr_texture(nullptr), curr_render_target(nullptr), curr_poly(nullptr),
+	d3dx_create_effect_from_file_ptr(nullptr)
 {
 }
 
@@ -819,6 +820,8 @@ int shaders::create_resources()
 
 void shaders::begin_draw()
 {
+	double t;
+
 	if (!enabled())
 	{
 		return;
@@ -826,6 +829,10 @@ void shaders::begin_draw()
 
 	curr_screen = 0;
 	curr_effect = default_effect;
+	// Update for delta_time
+	t = machine->time().as_double();
+	delta_t = t - acc_t;
+	acc_t = t;
 
 	default_effect->set_technique("ScreenTechnique");
 	post_effect->set_technique("DefaultTechnique");
@@ -900,7 +907,6 @@ void shaders::blit(
 	curr_effect->end();
 }
 
-
 //============================================================
 //  shaders::find_render_target
 //============================================================
@@ -1069,11 +1075,13 @@ int shaders::phosphor_pass(d3d_render_target *rt, int source_index, poly_info *p
 		return next_index;
 	}
 
+	// Shader needs time between last update
 	curr_effect = phosphor_effect;
 	curr_effect->update_uniforms();
 	curr_effect->set_texture("Diffuse", rt->target_texture[next_index]);
 	curr_effect->set_texture("LastPass", rt->cache_texture);
 	curr_effect->set_bool("Passthrough", false);
+	curr_effect->set_float("DeltaTime", delta_time());
 
 	next_index = rt->next_index(next_index);
 	blit(rt->target_surface[next_index], false, D3DPT_TRIANGLELIST, 0, 2);
diff --git a/src/osd/modules/render/d3d/d3dhlsl.h b/src/osd/modules/render/d3d/d3dhlsl.h
index a2c50cb..ed25d2c 100644
--- a/src/osd/modules/render/d3d/d3dhlsl.h
+++ b/src/osd/modules/render/d3d/d3dhlsl.h
@@ -319,7 +319,8 @@ private:
 	void                    enumerate_screens();
 
 	void                    render_snapshot(IDirect3DSurface9 *surface);
-
+	// Time since last call, only updates once per render of all screens
+	double                  delta_time() { return delta_t; }
 	d3d_render_target*      find_render_target(int source_width, int source_height, uint32_t screen_index);
 
 	rgb_t                   apply_color_convolution(rgb_t color);
@@ -349,6 +350,8 @@ private:
 	bool                    oversampling_enable;        // oversampling enable flag
 	int                     num_screens;                // number of emulated physical screens
 	int                     curr_screen;                // current screen for render target operations
+	double                  acc_t;                      // accumulated machine time
+	double                  delta_t;                    // data for delta_time
 	bitmap_argb32           shadow_bitmap;              // shadow mask bitmap for post-processing shader
 	texture_info *          shadow_texture;             // shadow mask texture for post-processing shader
 	hlsl_options *          options;                    // current options
diff --git a/src/osd/modules/sound/xaudio2_sound.cpp b/src/osd/modules/sound/xaudio2_sound.cpp
index 3c76ac1..6667fe7 100644
--- a/src/osd/modules/sound/xaudio2_sound.cpp
+++ b/src/osd/modules/sound/xaudio2_sound.cpp
@@ -123,9 +123,6 @@ public:
 typedef std::unique_ptr<IXAudio2MasteringVoice, xaudio2_custom_deleter> mastering_voice_ptr;
 typedef std::unique_ptr<IXAudio2SourceVoice, xaudio2_custom_deleter> src_voice_ptr;
 
-// Typedef for pointer to XAudio2Create
-typedef HRESULT (WINAPI *xaudio2_create_ptr)(IXAudio2 **, uint32_t, XAUDIO2_PROCESSOR);
-
 //============================================================
 //  Helper classes
 //============================================================
@@ -205,9 +202,9 @@ private:
 	uint32_t                           m_overflows;
 	uint32_t                           m_underflows;
 	BOOL                             m_in_underflow;
-	osd::dynamic_module::ptr         m_xaudio_dll;
-	xaudio2_create_ptr               XAudio2Create;
 	BOOL                             m_initialized;
+	OSD_DYNAMIC_API(xaudio2, "dwrite.dll");
+	OSD_DYNAMIC_API_FN(xaudio2, HRESULT, WINAPI, XAudio2Create, IXAudio2 **, uint32_t, XAUDIO2_PROCESSOR);
 
 public:
 	sound_xaudio2() :
@@ -228,7 +225,6 @@ public:
 		m_overflows(0),
 		m_underflows(0),
 		m_in_underflow(FALSE),
-		XAudio2Create(nullptr),
 		m_initialized(FALSE)
 	{
 	}
@@ -268,13 +264,7 @@ private:
 
 bool sound_xaudio2::probe()
 {
-	m_xaudio_dll = osd::dynamic_module::open({ "XAudio2_9.dll", "XAudio2_8.dll" });
-	if (m_xaudio_dll == nullptr)
-		return false;
-
-	XAudio2Create = m_xaudio_dll->bind<xaudio2_create_ptr>("XAudio2Create");
-
-	return (XAudio2Create ? true : false);
+	return OSD_DYNAMIC_API_TEST(XAudio2Create);
 }
 
 //============================================================
@@ -291,14 +281,14 @@ int sound_xaudio2::init(osd_options const &options)
 	CoInitializeEx(nullptr, COINIT_MULTITHREADED);
 
 	// Make sure our XAudio2Create entrypoint is bound
-	if (!XAudio2Create)
+	if (!OSD_DYNAMIC_API_TEST(XAudio2Create))
 	{
 		osd_printf_error("Could not find XAudio2. Please try to reinstall DirectX runtime package.\n");
 		return 1;
 	}
 
 	// Create the IXAudio2 object
-	HR_GOERR(this->XAudio2Create(m_xAudio2.GetAddressOf(), 0, XAUDIO2_DEFAULT_PROCESSOR));
+	HR_GOERR(OSD_DYNAMIC_CALL(XAudio2Create, m_xAudio2.GetAddressOf(), 0, XAUDIO2_DEFAULT_PROCESSOR));
 
 	// make a format description for what we want
 	format.wBitsPerSample = 16;
diff --git a/src/osd/uwp/uwpcompat.cpp b/src/osd/uwp/uwpcompat.cpp
index e550a42..156ab40 100644
--- a/src/osd/uwp/uwpcompat.cpp
+++ b/src/osd/uwp/uwpcompat.cpp
@@ -66,16 +66,14 @@ extern "C" {
 		return osd_ticks();
 	}
 
+	// This is only in here so callers get an error
 	HMODULE WINAPI LoadLibraryExA(
 		_In_ LPCSTR lpLibFileName,
 		_Reserved_ HANDLE hFile,
 		_In_ DWORD dwFlags
-		)
+	)
 	{
-		wchar_t libfile_wide[MAX_PATH + 1];
-		if (MultiByteToWideChar(CP_ACP, 0, lpLibFileName, strlen(lpLibFileName), libfile_wide, MAX_PATH))
-			return LoadPackagedLibrary(libfile_wide, 0);
-
+		SetLastError(ERROR_FILE_NOT_FOUND);
 		return nullptr;
 	}
 
@@ -83,9 +81,10 @@ extern "C" {
 		_In_ LPCWSTR lpLibFileName,
 		_Reserved_ HANDLE hFile,
 		_In_ DWORD dwFlags
-		)
+	)
 	{
-		return LoadPackagedLibrary(lpLibFileName, 0);
+		SetLastError(ERROR_FILE_NOT_FOUND);
+		return nullptr;
 	}
 
 	DWORD WINAPI GetFileSize(
diff --git a/src/osd/uwp/uwpcompat.h b/src/osd/uwp/uwpcompat.h
index f155e22..697d5f9 100644
--- a/src/osd/uwp/uwpcompat.h
+++ b/src/osd/uwp/uwpcompat.h
@@ -72,7 +72,7 @@ LoadLibraryExA(
 	_In_ LPCSTR lpLibFileName,
 	_Reserved_ HANDLE hFile,
 	_In_ DWORD dwFlags
-	);
+);
 
 _Ret_maybenull_
 HMODULE
@@ -81,7 +81,7 @@ LoadLibraryExW(
 	_In_ LPCWSTR lpLibFileName,
 	_Reserved_ HANDLE hFile,
 	_In_ DWORD dwFlags
-	);
+);
 
 DWORD
 WINAPI
diff --git a/src/tools/imgtool/imgtool.cpp b/src/tools/imgtool/imgtool.cpp
index 322dbe8..bb7e6c8 100644
--- a/src/tools/imgtool/imgtool.cpp
+++ b/src/tools/imgtool/imgtool.cpp
@@ -67,18 +67,6 @@ char *strncpyz(char *dest, const char *source, size_t len)
 	return s;
 }
 
-char *strncatz(char *dest, const char *source, size_t len)
-{
-	size_t l;
-	l = strlen(dest);
-	dest += l;
-	if (len > l)
-		len -= l;
-	else
-		len = 0;
-	return strncpyz(dest, source, len);
-}
-
 //-------------------------------------------------
 //  markerrorsource - marks where an error source
 //-------------------------------------------------
@@ -881,7 +869,7 @@ char *imgtool_temp_str(void)
 
 ***************************************************************************/
 
-imgtoolerr_t imgtool::image::internal_open(const imgtool_module *module, const char *fname,
+imgtoolerr_t imgtool::image::internal_open(const imgtool_module *module, const std::string &filename,
 	int read_or_write, util::option_resolution *createopts, imgtool::image::ptr &outimg)
 {
 	imgtoolerr_t err;
@@ -908,7 +896,7 @@ imgtoolerr_t imgtool::image::internal_open(const imgtool_module *module, const c
 	}
 
 	// open the stream
-	stream = imgtool::stream::open(fname, read_or_write);
+	stream = imgtool::stream::open(filename, read_or_write);
 	if (!stream)
 	{
 		err = (imgtoolerr_t)(IMGTOOLERR_FILENOTFOUND | IMGTOOLERR_SRC_IMAGEFILE);
@@ -964,7 +952,7 @@ done:
 //  open - open an image
 //-------------------------------------------------
 
-imgtoolerr_t imgtool::image::open(const imgtool_module *module, const char *filename, int read_or_write, ptr &outimg)
+imgtoolerr_t imgtool::image::open(const imgtool_module *module, const std::string &filename, int read_or_write, ptr &outimg)
 {
 	read_or_write = read_or_write ? OSD_FOPEN_RW : OSD_FOPEN_READ;
 	return internal_open(module, filename, read_or_write, nullptr, outimg);
@@ -975,7 +963,7 @@ imgtoolerr_t imgtool::image::open(const imgtool_module *module, const char *file
 //  imgtool::image::open_byname - open an image
 //-------------------------------------------------
 
-imgtoolerr_t imgtool::image::open(const std::string &modulename, const char *filename, int read_or_write, ptr &outimg)
+imgtoolerr_t imgtool::image::open(const std::string &modulename, const std::string &filename, int read_or_write, ptr &outimg)
 {
 	const imgtool_module *module;
 
@@ -1016,7 +1004,7 @@ imgtool::image::~image()
 //  create - creates an image
 //-------------------------------------------------
 
-imgtoolerr_t imgtool::image::create(const imgtool_module *module, const char *fname,
+imgtoolerr_t imgtool::image::create(const imgtool_module *module, const std::string &filename,
 	util::option_resolution *opts, ptr &image)
 {
 	std::unique_ptr<util::option_resolution> alloc_resolution;
@@ -1033,7 +1021,7 @@ imgtoolerr_t imgtool::image::create(const imgtool_module *module, const char *fn
 		opts = alloc_resolution.get();
 	}
 
-	return internal_open(module, fname, OSD_FOPEN_RW_CREATE, opts, image);
+	return internal_open(module, filename, OSD_FOPEN_RW_CREATE, opts, image);
 }
 
 
@@ -1041,7 +1029,7 @@ imgtoolerr_t imgtool::image::create(const imgtool_module *module, const char *fn
 //  create - creates an image
 //-------------------------------------------------
 
-imgtoolerr_t imgtool::image::create(const std::string &modulename, const char *fname, util::option_resolution *opts, ptr &image)
+imgtoolerr_t imgtool::image::create(const std::string &modulename, const std::string &filename, util::option_resolution *opts, ptr &image)
 {
 	const imgtool_module *module;
 
@@ -1049,7 +1037,7 @@ imgtoolerr_t imgtool::image::create(const std::string &modulename, const char *f
 	if (!module)
 		return (imgtoolerr_t)(IMGTOOLERR_MODULENOTFOUND | IMGTOOLERR_SRC_MODULE);
 
-	return create(module, fname, opts, image);
+	return create(module, filename, opts, image);
 }
 
 
@@ -1057,11 +1045,11 @@ imgtoolerr_t imgtool::image::create(const std::string &modulename, const char *f
 //  create - creates an image
 //-------------------------------------------------
 
-imgtoolerr_t imgtool::image::create(const imgtool_module *module, const char *fname,
+imgtoolerr_t imgtool::image::create(const imgtool_module *module, const std::string &filename,
 	util::option_resolution *opts)
 {
 	std::unique_ptr<image> image;
-	return create(module, fname, opts, image);
+	return create(module, filename, opts, image);
 }
 
 
@@ -1069,10 +1057,10 @@ imgtoolerr_t imgtool::image::create(const imgtool_module *module, const char *fn
 //  create - creates an image
 //-------------------------------------------------
 
-imgtoolerr_t imgtool::image::create(const std::string &modulename, const char *fname, util::option_resolution *opts)
+imgtoolerr_t imgtool::image::create(const std::string &modulename, const std::string &filename, util::option_resolution *opts)
 {
 	std::unique_ptr<image> image;
-	return create(modulename, fname, opts, image);
+	return create(modulename, filename, opts, image);
 }
 
 
@@ -2416,8 +2404,9 @@ imgtool::directory::directory(imgtool::partition &partition)
 //  enumerating files on a partition
 //-------------------------------------------------
 
-imgtoolerr_t imgtool::directory::open(imgtool::partition &partition, const char *path, imgtool::directory::ptr &outenum)
+imgtoolerr_t imgtool::directory::open(imgtool::partition &partition, const std::string &path_string, imgtool::directory::ptr &outenum)
 {
+	const char *path = path_string.c_str();
 	imgtoolerr_t err = (imgtoolerr_t)IMGTOOLERR_SUCCESS;
 	imgtool::directory::ptr enumeration;
 	char *alloc_path = nullptr;
diff --git a/src/tools/imgtool/imgtool.h b/src/tools/imgtool/imgtool.h
index fb1b602..eb614a9 100644
--- a/src/tools/imgtool/imgtool.h
+++ b/src/tools/imgtool/imgtool.h
@@ -98,12 +98,12 @@ namespace imgtool
 		~image();
 
 		static imgtoolerr_t identify_file(const char *filename, imgtool_module **modules, size_t count);
-		static imgtoolerr_t open(const imgtool_module *module, const char *filename, int read_or_write, ptr &outimg);
-		static imgtoolerr_t open(const std::string &modulename, const char *filename, int read_or_write, ptr &outimg);
-		static imgtoolerr_t create(const imgtool_module *module, const char *fname, util::option_resolution *opts, ptr &image);
-		static imgtoolerr_t create(const std::string &modulename, const char *fname, util::option_resolution *opts, ptr &image);
-		static imgtoolerr_t create(const imgtool_module *module, const char *fname, util::option_resolution *opts);
-		static imgtoolerr_t create(const std::string &modulename, const char *fname, util::option_resolution *opts);
+		static imgtoolerr_t open(const imgtool_module *module, const std::string &filename, int read_or_write, ptr &outimg);
+		static imgtoolerr_t open(const std::string &modulename, const std::string &filename, int read_or_write, ptr &outimg);
+		static imgtoolerr_t create(const imgtool_module *module, const std::string &filename, util::option_resolution *opts, ptr &image);
+		static imgtoolerr_t create(const std::string &modulename, const std::string &filename, util::option_resolution *opts, ptr &image);
+		static imgtoolerr_t create(const imgtool_module *module, const std::string &filename, util::option_resolution *opts);
+		static imgtoolerr_t create(const std::string &modulename, const std::string &filename, util::option_resolution *opts);
 		static uint64_t rand();
 
 		std::string info();
@@ -129,7 +129,7 @@ namespace imgtool
 		// better C++ adoption (e.g. - std::unique_ptr<>, std:move() etc)
 		bool m_okay_to_close;
 
-		static imgtoolerr_t internal_open(const imgtool_module *module, const char *fname,
+		static imgtoolerr_t internal_open(const imgtool_module *module, const std::string &filename,
 			int read_or_write, util::option_resolution *createopts, imgtool::image::ptr &outimg);
 	};
 }
@@ -244,7 +244,7 @@ namespace imgtool
 		~directory();
 
 		// methods
-		static imgtoolerr_t open(imgtool::partition &partition, const char *path, ptr &outenum);
+		static imgtoolerr_t open(imgtool::partition &partition, const std::string &path, ptr &outenum);
 		imgtoolerr_t get_next(imgtool_dirent &ent);
 
 		// accessors
@@ -265,7 +265,6 @@ int imgtool_validitychecks(void);
 void unknown_partition_get_info(const imgtool_class *imgclass, uint32_t state, union imgtoolinfo *info);
 
 char *strncpyz(char *dest, const char *source, size_t len);
-char *strncatz(char *dest, const char *source, size_t len);
 void rtrim(char *buf);
 
 #endif /* IMGTOOL_H */
diff --git a/src/tools/imgtool/main.cpp b/src/tools/imgtool/main.cpp
index f108779..5416b6d 100644
--- a/src/tools/imgtool/main.cpp
+++ b/src/tools/imgtool/main.cpp
@@ -177,12 +177,21 @@ static int cmd_dir(const struct command *c, int argc, char *argv[])
 	imgtool::partition::ptr partition;
 	imgtool::directory::ptr imgenum;
 	imgtool_dirent ent;
-	char buf[512];
 	char last_modified[19];
-	const char *path;
+	std::string path;
 	int partition_index = 0;
 	std::string info;
 
+	// build the separator
+	const int columnwidth_filename = 30;
+	const int columnwidth_filesize = 8;
+	const int columnwidth_attributes = 15;
+	const int columnwidth_lastmodified = 18;
+	std::string separator = std::string(columnwidth_filename, '-') + " "
+		+ std::string(columnwidth_filesize, '-') + " "
+		+ std::string(columnwidth_attributes, '-') + " "
+		+ std::string(columnwidth_lastmodified, '-');
+
 	// attempt to open image
 	err = imgtool::image::open(argv[0], argv[1], OSD_FOPEN_READ, image);
 	if (err)
@@ -193,7 +202,7 @@ static int cmd_dir(const struct command *c, int argc, char *argv[])
 	if (err)
 		goto done;
 
-	path = argc > 2 ? argv[2] : nullptr;
+	path = argc > 2 ? argv[2] : "";
 
 	err = imgtool::directory::open(*partition, path, imgenum);
 	if (err)
@@ -204,19 +213,19 @@ static int cmd_dir(const struct command *c, int argc, char *argv[])
 	total_count = 0;
 	total_size = 0;
 
-	fprintf(stdout, "Contents of %s:%s\n", argv[1], path ? path : "");
+	fprintf(stdout, "Contents of %s:%s\n", argv[1], path.c_str());
 
 	info = image->info();
 	if (!info.empty())
 		fprintf(stdout, "%s\n", info.c_str());
-	fprintf(stdout, "------------------------------  --------  ---------------  ------------------\n");
+
+	fprintf(stdout, "%s\n", separator.c_str());
 
 	while (((err = imgenum->get_next(ent)) == 0) && !ent.eof)
 	{
-		if (ent.directory)
-			snprintf(buf, sizeof(buf), "<DIR>");
-		else
-			snprintf(buf, sizeof(buf), "%u", (unsigned int) ent.filesize);
+		std::string filesize_string = ent.directory
+			? "<DIR>"
+			: string_format("%u", (unsigned int) ent.filesize);
 
 		if (ent.lastmodified_time != 0)
 			strftime(last_modified, sizeof(last_modified), "%d-%b-%y %H:%M:%S",
@@ -225,7 +234,11 @@ static int cmd_dir(const struct command *c, int argc, char *argv[])
 		if (ent.hardlink)
 			strcat(ent.filename, " <hl>");
 
-		fprintf(stdout, "%-30s  %8s  %15s  %18s\n", ent.filename, buf, ent.attr, last_modified);
+		fprintf(stdout, "%*s %*s %*s %*s\n",
+			-columnwidth_filename, ent.filename,
+			columnwidth_filesize, filesize_string.c_str(),
+			columnwidth_attributes, ent.attr,
+			columnwidth_lastmodified, last_modified);
 
 		if (ent.softlink && ent.softlink[0] != '\0')
 			fprintf(stdout, "-> %s\n", ent.softlink);
@@ -244,7 +257,7 @@ static int cmd_dir(const struct command *c, int argc, char *argv[])
 	if (err)
 		goto done;
 
-	fprintf(stdout, "------------------------  ------ ---------------\n");
+	fprintf(stdout, "%s\n", separator.c_str());
 	fprintf(stdout, "%8i File(s)        %8i bytes\n", total_count, total_size);
 	if (!freespace_err)
 		fprintf(stdout, "                        %8u bytes free\n", (unsigned int) freespace);
diff --git a/src/tools/imgtool/stream.cpp b/src/tools/imgtool/stream.cpp
index d5d0ee1..0bcca45 100644
--- a/src/tools/imgtool/stream.cpp
+++ b/src/tools/imgtool/stream.cpp
@@ -24,7 +24,6 @@
 imgtool::stream::stream(bool wp)
 	: imgtype(IMG_FILE)
 	, write_protect(wp)
-	, name(nullptr)
 	, position(0)
 	, filesize(0)
 	, file()
@@ -40,7 +39,6 @@ imgtool::stream::stream(bool wp)
 imgtool::stream::stream(bool wp, util::core_file::ptr &&f)
 	: imgtype(IMG_FILE)
 	, write_protect(wp)
-	, name(nullptr)
 	, position(0)
 	, filesize(f->size())
 	, file(std::move(f))
@@ -56,7 +54,6 @@ imgtool::stream::stream(bool wp, util::core_file::ptr &&f)
 imgtool::stream::stream(bool wp, std::size_t size)
 	: imgtype(IMG_MEM)
 	, write_protect(wp)
-	, name(nullptr)
 	, position(0)
 	, filesize(size)
 	, file()
@@ -72,7 +69,6 @@ imgtool::stream::stream(bool wp, std::size_t size)
 imgtool::stream::stream(bool wp, std::size_t size, void *buf)
 	: imgtype(IMG_MEM)
 	, write_protect(wp)
-	, name(nullptr)
 	, position(0)
 	, filesize(size)
 	, file()
@@ -96,13 +92,13 @@ imgtool::stream::~stream()
 //  open_zip
 //-------------------------------------------------
 
-imgtool::stream::ptr imgtool::stream::open_zip(const char *zipname, const char *subname, int read_or_write)
+imgtool::stream::ptr imgtool::stream::open_zip(const std::string &zipname, const char *subname, int read_or_write)
 {
 	if (read_or_write)
 		return imgtool::stream::ptr();
 
 	/* check to see if the file exists */
-	FILE *f = fopen(zipname, "r");
+	FILE *f = fopen(zipname.c_str(), "r");
 	if (!f)
 		return imgtool::stream::ptr();
 	fclose(f);
@@ -139,7 +135,7 @@ imgtool::stream::ptr imgtool::stream::open_zip(const char *zipname, const char *
 //  open
 //-------------------------------------------------
 
-imgtool::stream::ptr imgtool::stream::open(const char *fname, int read_or_write)
+imgtool::stream::ptr imgtool::stream::open(const std::string &filename, int read_or_write)
 {
 	static const uint32_t write_modes[] =
 	{
@@ -151,22 +147,22 @@ imgtool::stream::ptr imgtool::stream::open(const char *fname, int read_or_write)
 	imgtool::stream::ptr s;
 	char c;
 
-	/* maybe we are just a ZIP? */
-	const char *ext = strrchr(fname, '.');
-	if (ext && !core_stricmp(ext, ".zip"))
-		return open_zip(fname, nullptr, read_or_write);
+	// maybe we are just a ZIP?
+	std::string ext = core_filename_extract_extension(filename);
+	if (!core_stricmp(ext.c_str(), ".zip"))
+		return open_zip(filename, nullptr, read_or_write);
 
 	util::core_file::ptr f = nullptr;
-	auto const filerr = util::core_file::open(fname, write_modes[read_or_write], f);
+	auto const filerr = util::core_file::open(filename, write_modes[read_or_write], f);
 	if (filerr != osd_file::error::NONE)
 	{
 		if (!read_or_write)
 		{
-			int const len = strlen(fname);
+			int const len = filename.size();
 
 			/* can't open the file; try opening ZIP files with other names */
 			std::vector<char> buf(len + 1);
-			strcpy(&buf[0], fname);
+			strcpy(&buf[0], filename.c_str());
 
 			for (int i = len-1; !s && (i >= 0); i--)
 			{
@@ -189,8 +185,7 @@ imgtool::stream::ptr imgtool::stream::open(const char *fname, int read_or_write)
 
 	imgtool::stream::ptr imgfile(new imgtool::stream(read_or_write ? false : true, std::move(f)));
 
-	/* Normal file */
-	imgfile->name = fname;
+	// normal file
 	return imgfile;
 }
 
diff --git a/src/tools/imgtool/stream.h b/src/tools/imgtool/stream.h
index 9a99d96..4d968ca 100644
--- a/src/tools/imgtool/stream.h
+++ b/src/tools/imgtool/stream.h
@@ -23,7 +23,7 @@ namespace imgtool
 
 		~stream();
 
-		static imgtool::stream::ptr open(const char *fname, int read_or_write);  /* similar params to mame_fopen */
+		static imgtool::stream::ptr open(const std::string &filename, int read_or_write);  /* similar params to mame_fopen */
 		static imgtool::stream::ptr open_write_stream(int filesize);
 		static imgtool::stream::ptr open_mem(void *buf, size_t sz);
 
@@ -61,7 +61,6 @@ namespace imgtool
 
 		imgtype_t       imgtype;
 		bool            write_protect;
-		const char      *name; // needed for clear
 		std::uint64_t   position;
 		std::uint64_t   filesize;
 
@@ -75,7 +74,7 @@ namespace imgtool
 		stream(bool wp, std::size_t size, void *buf);
 
 		// private methods
-		static stream::ptr open_zip(const char *zipname, const char *subname, int read_or_write);
+		static stream::ptr open_zip(const std::string &zipname, const char *subname, int read_or_write);
 	};
 }
 
diff --git a/uismall.bdf b/uismall.bdf
index ded3d1f..948b4d9 100644
--- a/uismall.bdf
+++ b/uismall.bdf
@@ -3,7 +3,7 @@ COMMENT Copyright (C) 1997-2016  MAMEDev and contributors
 FONT -mamedev-uismall-Medium-R-Normal--16-120-96-96-P-100-ISO10646-1
 SIZE 12 96 96
 FONTBOUNDINGBOX 8 11 0 -2
-STARTPROPERTIES 17
+STARTPROPERTIES 18
 POINT_SIZE 120
 PIXEL_SIZE 16
 RESOLUTION_X 96
@@ -21,6 +21,7 @@ SETWIDTH_NAME "Normal"
 ADD_STYLE_NAME ""
 CHARSET_REGISTRY "ISO10646"
 CHARSET_ENCODING "1"
+DEFAULT_CHAR 173
 ENDPROPERTIES
 CHARS 1024
 STARTCHAR space
@@ -1563,8 +1564,8 @@ E8
 ENDCHAR
 STARTCHAR paragraph
 ENCODING 182
-SWIDTH 375 0
-DWIDTH 6 0
+SWIDTH 437 0
+DWIDTH 7 0
 BBX 6 9 0 -2
 BITMAP
 7C
diff --git a/whatsnew.txt b/whatsnew.txt
index 1e07b1f..3a48284 100644
--- a/whatsnew.txt
+++ b/whatsnew.txt
@@ -1,556 +1,494 @@
-0.180
+0.181
 -----
 
 
 MAMETesters Bugs Fixed
 ----------------------
-- 06436: [DIP/Input] (tecmo.cpp) gemini, geminib: Input issues (Tafoid)
-- 06432: [Graphics] Creating a game specific INI disables HLSL filters (Jezze)
-- 04933: [Flip Screen/Cocktail] (gaiden.cpp) gaiden and clones: Very slight offset down on flip screen (Osso)
-- 06427: [Documentation] (atarisy1.cpp) peterpak: A dash too much in the game description. (AntoPISA)
-- 03646: [Graphics] (segas16b.cpp) altbeastj, altbeast6 : Missing graphics in the crystal ball. (David Haywood)
-- 06407: [Compiling] (cps2.cpp) BUILD: Compiling a tinybuild with cps2 driver included crashes (smf)
-- 06413: [Interface] CONSOLE: Does nothing but allow "EXIT" (crazyc)
-- 05928: [Crash/Freeze] (zn.cpp) nbajamex: game crashes / nvram gets corrupted (Phil Bennett)
-- 06418: [Flip Screen/Cocktail] (8080bw.cpp) Color sets in 8080bw: No picture for second player in cocktail mode. (Robbbert)
-- 06417: [Crash/Freeze] MAME crashed with UI and HLSL (Jezze)
-- 06411: [Flip Screen/Cocktail] (equites.cpp) splndrbt and clones, hvoltage: Cocktail mode video isn't working correctly (Osso)
+- 00101: [Misc.] (kaneko16.cpp) berlwallt, berlwallk: an error message "Copy Board" pops up. (Angelo Salese)
+- 02855: [DIP/Input] (hanaawas.cpp) hanaawas: Credits dip switch does not work (Angelo Salese)
+- 04796: [Flip Screen/Cocktail] (m58.cpp) 10yard and clones: Flip Screen/Cocktail Mode offset (Robbbert)
+- 04921: [Flip Screen/Cocktail] (fcrash.cpp) fcrash: Game sprites not flipped when Flip Screen is ON (Robbbert)
+- 04922: [Flip Screen/Cocktail] (finalizr.cpp) All sets in finalizr.c: Ships and scores should both be on top when screen is Flipped
+  (Robbbert)
+- 05006: [Graphics] (gb.cpp) gameboy [f1race]: Corrupted graphics (racetrack not lined up) (Wilbert Pol)
+- 06338: [DIP/Input] (mz2000.cpp) mz2000, mz2200: Mistakes in current keyboard matrix emulation and missing keys ! (AJR)
+- 06440: [Gameplay] (segag80r.cpp) Most/all sets in segag80r.cpp: game resets itself during play (smf)
+- 06449: [Color/Palette] (8080bw.cpp) sicv, sicv1, invadpt2, invadpt2br, moonbase, moonbasea: In a 2-player game, colors don't
+  change at certain areas of the screen for each player's turn. (Robbbert)
+- 06450: [Color/Palette] (astinvad.cpp) spcking2: Incorrect colors at certain areas of the screen. (Robbbert)
+- 06451: [DIP/Input] (ccastles.cpp) All sets in ccastles.cpp: Map Button 2 to start a 2-player game in upright mode. (Tafoid)
+- 06452: [Flip Screen/Cocktail] (phoenix.cpp) phoenix: Cocktail Mode displays incorrectly (Robbbert)
 
 
 New working machines
 --------------------
-Candela CAN09 terminal [Joakim Larsson Edstrom]
-Draw 88 Poker (V2.0) [Roberto Fresca, Charles MacDonald]
-Entex Space Battle [hap, Sean Riddle]
-Fidelity Designer 2100 Display [hap, Berger]
-Fidelity Excel 68000 [hap, Berger]
-Mephisto Montreux [unknown]
-Player's Edge Plus (PP0001) Standard Draw Poker [BrianT]
-Player's Edge Plus (PP0050) Joker Poker (4 sets) [BrianT]
-Player's Edge Plus (PP0054) Deuces Wild Poker (El Cortez) [BrianT]
-Player's Edge Plus (PP0195) 4 of a Kind Bonus Poker [BrianT]
-Player's Edge Plus (PP0218) 4 of a Kind Bonus Poker [BrianT]
-Player's Edge Plus (PP0232) Patriot Poker [BrianT]
-Player's Edge Plus (PP0294) Aces and Faces Bonus Joker Poker [BrianT]
-Player's Edge Plus (PP0295) Super Deuces Wild Poker [BrianT]
-Player's Edge Plus (PP0445) Aces and Faces Bonus Joker Poker [BrianT]
-Player's Edge Plus (PP0450) Loose Deuce Deuces Wild! Poker [BrianT]
-Player's Edge Plus (PP0453) Joker Poker [BrianT]
-Player's Edge Plus (X002002P+XP000038) Double Double Bonus Poker [BrianT]
-Player's Edge Plus (X002240P+XP000038) Joker Poker (Two Pair or Better) [BrianT]
-Radio Shack Monkey See [hap, Sean Riddle]
-Bandai System Control Car: Cheetah/The Incredible Brain Buggy [hap, Sean Riddle]
-Shikigami no Shiro - internal build (V1.02J 2001/09/27 18:45) [rtw, ShouTime, smf, O.Galibert]
+Eeekk! [Andrew Welburn, Craig Anstett, smf]
+Intel iSBC 286/10 [Al Kossow]
 Intel iSBC 286/12 [Al Kossow]
+Miss World 2002 [NeoGeo de Ahuizotla, Artemio Urbina, The Dumping Union]
+Player's Edge Plus (XMP00011) 5-in-1 Wingboard (CG2298) [BrianT]
+Power Flipper Pinball Shooting v1.33 [Jorge Silva]
+Quiz Kid Racer [hap, Sean Riddle]
+Steering Champ (GQ710 VER. UAA) [Bill D. / The Dumping Union, crzmx, smf]
+Tokio / Scramble Formation (newer) [ShouTime, brizzo, David Haywood]
 
 
 New working clones
 ------------------
-1945k III (newer, OPCX1 PCB) [ShouTime, The Dumping Union]
-Blue Shark (Model Racing bootleg) [f205v]
-Burning Fight (prototype, ver 23.3, 910326) [Collin Foust]
-Cosmic Invaders (bootleg of Space Invaders) [penrhos]
-Forgotten Worlds (USA, B-Board 88618B-2, Rev. B) [Corrado Tomaselli, The Dumping Union]
-Gran Premio F1 (Spanish bootleg of Pole Position II) [Rockman, Arcade Hacker]
-Grand Prix Star (v3.0) [Hammy]
-Hit the Ice (US, with riser board) [coolmod]
-Mustache Boy (Italy) [ShouTime]
-Metal Slug 2 Turbo (hack/bootleg) [system11, trap15]
-Ozma Wars (Model Racing bootleg) [f205v]
-Player's Edge Plus (PP0008) Standard Draw Poker (set 2, El Cortez) [BrianT]
-Player's Edge Plus (PP0048) Joker Poker (set 4) [BrianT]
-Player's Edge Plus (PP0057) Deuces Wild Poker (set 4) [BrianT]
-Player's Edge Plus (PP0103) Deuces Wild Poker (set 2) [BrianT]
-Player's Edge Plus (PP0126) Deuces Wild Poker (set 3) [BrianT]
-Player's Edge Plus (PP0188) Standard Draw Poker (set 3) [BrianT]
-Player's Edge Plus (PP0434) Bonus Poker Deluxe (set 2) [BrianT]
-Player's Edge Plus (PP0447) Standard Draw Poker (set 3) [BrianT]
-Player's Edge Plus (PP0452) Double Deuces Wild Poker (set 2) [BrianT]
-Road Fighter (set 3, conversion hack on Hyper Sports PCB) [f205v]
-Sol Divide - The Sword Of Darkness (Korea) [Nomax, The Dumping Union]
-Stone Ball (2 Players, v1-20 21/10/1994) [Nomax, The Dumping Union]
-Vendetta (World, 2 Players, ver. ?) [Corrado Tomaselli, The Dumping Union]
+Fidelity Designer 2000 Display [yovan]
+Flicky (128k Version, 315-5051, larger roms) [system11]
+Golden Crown Hopper [Gerald COY]
+Mahjong Clinic (Japan, set 2) [system11]
+Momoko 120% (English text) [Paul Hogger]
+Multi Wars (bootleg of UniWar S) [Paul Hogger]
+Raiden (Korea, bootleg) [Tirino73]
+Real Bout Fatal Fury / Real Bout Garou Densetsu (Korean release) [Brian Hargrove]
+Same! Same! Same! (1P set, NEW VER! hack) [CAPS0ff, trap15]
+Side by Side 2 Evoluzione RR (Ver 3.1 J) [ShouTime, The Dumping Union]
+Simpson Junior (bootleg of J. J. Squawkers) [NeoGeo de Ahuizotla, Artemio Urbina, The Dumping Union]
+Space Dungeon (larger roms) [Ordyne, The Dumping Union]
+Super Visual Football: European Sega Cup (original rev) [Gerald COY]
+The NewZealand Story (World, old version) (older PCB) [Porchy, The Dumping Union]
+Tokio / Scramble Formation (older) [ShouTime, brizzo, David Haywood]
+Tokio / Scramble Formation (US) [ShouTime, brizzo, David Haywood]
+Turbo Force (US) [dos_]
+VTech Laser Turbo XT [Miodrag Milanovic]
+VTech Laser XT/3 [Miodrag Milanovic]
 
 
 Machines promoted to working
 ----------------------------
-Exzisus (EX 1.0, Magnet System, prototype) [David Haywood]
-Go By RC (V2.03O 1999/05/25 13:31) [smf]
-Number Crash [kurobee]
-Saitek RISC 2500 v1.04 [unknown]
-Space Lords (rev C) [Morten Shearman Kirkegaard, Samuel Neves, Peter Wilhelmsen]
-Tandy/Memorex Video Information System MD-2500 [Carl]
-Time Scanner (TS 2.0, Magnet System, prototype) [David Haywood]
-Xain'd Sleena (SC 3.0, Magnet System, prototype) [David Haywood]
-Intel iSBC 286/10 [Carl]
+ACT Apricot PC [Dirk Best]
+ACT Apricot Xi [Dirk Best]
+K28: Talking Learning Computer (model 7-230) [O. Galibert]
+Mattel Funtronics Jacks [hap, Sean Riddle]
+Mattel Funtronics Red Light Green Light [hap, Sean Riddle]
 
 
 Clones promoted to working
 --------------------------
-RC De Go (V2.03J 1999/05/22 19:29) [smf]
-Space Lords (rev A) [Morten Shearman Kirkegaard, Samuel Neves, Peter Wilhelmsen]
-Space Lords (rev A, German) [Morten Shearman Kirkegaard, Samuel Neves, Peter Wilhelmsen]
-Space Lords (rev B) [Morten Shearman Kirkegaard, Samuel Neves, Peter Wilhelmsen]
+Space Invader (Entex, COP444L version)
 
 
 New machines marked as NOT_WORKING
 ----------------------------------
-ACI Destiny Prodigy [Joakim Larsson Edstrom]
-Acorn A4000 [Nigel Barnes]
-Acorn A5000 [Nigel Barnes]
-Bandai Super Note Club mu (Japan) [Team Europe]
-Candela CAN09 main unit [Joakim Larsson Edstrom]
-Datum [Robbbert]
-Diamond Fever (0200302V, NSW/ACT) [Heihachi_73]
-GMX Micro 20 [Al Kossow, R. Belmont]
-Hazeltine 1500 [Al Kossow, Ryan Holtz]
-Intel iSBC 86/05 [Al Kossow]
-Intel iSBC 86/30 [Al Kossow]
-Jungle Juice (0200240V, New Zealand) [Heihachi_73]
-Kron K-180 [Joakim Larsson Edstrom]
-Meng Hong Lou [Guru, Dyq, Bnathan]
-Montana Choice (MG0025) Multi-Game [BrianT]
-Montana Choice (MG0026) Multi-Game [BrianT]
-Montana Choice (MG0182) Multi-Game [BrianT]
-Player's Choice (MG0213) Multi-Game [BrianT]
-Player's Edge (PK0858-PC075) Deuces Wild Poker (El Cortez) [BrianT]
-Player's Edge Plus (X000013K+XK000012) Keno [BrianT]
-Player's Edge Plus (X000846S+XS000006) Wild Star Red White & Blue Slots [BrianT]
-Player's Choice - Original (30143011, NSW/ACT) [Heihachi_73]
-Rider's Surf [PinMAME]
-Simatic PG675 [R. Belmont, rfka01]
-SYS68K/CPU-30SEN-R [Joakim Larsson Edstrom]
-SYS68K/CPU-30SEN-R-501 [Joakim Larsson Edstrom]
-Televideo TV910 [Al Kossow, R. Belmont]
+Apple Laser Writer II NT [Lord Nightmare, Joakim Larsson Edstrom]
+Back To the Future (2.8) [PinMAME]
+Dulmont Magnum [Carl, Dave Jones]
+Ensoniq SQ-2 [R. Belmont, Guru]
+Force SYS68K/CPU-20 [Joakim Larsson Edstrom]
+Knights of Valour 3 HD (V105) [XingXing]
+Monday Night Football (2.9, 50cts) [PinMAME]
+Multistar 3 [Heihachi_73]
+Royal Ascot II [Gerald COY, ShouTime, The Dumping Union]
 
 
 New clones marked as NOT_WORKING
 --------------------------------
-Acorn A3010 [Nigel Barnes]
-Acorn A3020 [Nigel Barnes]
-Acorn A4 [Nigel Barnes]
-Acorn A5000 Alpha [Nigel Barnes]
-Archimedes 3000 [Nigel Barnes]
-Archimedes 305 [Nigel Barnes]
-Archimedes 410/1 [Nigel Barnes]
-Archimedes 420/1 [Nigel Barnes]
-Archimedes 440 [Nigel Barnes]
-Archimedes 440/1 [Nigel Barnes]
-Archimedes 540 [Nigel Barnes]
-Cash Chameleon (0200437V, NSW/ACT) [Heihachi_73]
-Cash Chameleon (0300781V, New Zealand) [Heihachi_73]
-Chicken (0200530V, Queensland) [Heihachi_73]
-Inca Sun (CHG1458, US) [Heihachi_73]
-Star God (variable replay score) [PinMAME]
-SYS68K/CPU-30BE/16 [Joakim Larsson Edstrom]
-SYS68K/CPU-30BE/8 [Joakim Larsson Edstrom]
-SYS68K/CPU-30Lite/4 [Joakim Larsson Edstrom]
-SYS68K/CPU-30Lite/8 [Joakim Larsson Edstrom]
-SYS68K/CPU-30X [Joakim Larsson Edstrom]
-SYS68K/CPU-30XA [Joakim Larsson Edstrom]
-SYS68K/CPU-30ZA [Joakim Larsson Edstrom]
-SYS68K/CPU-30ZBE [Joakim Larsson Edstrom]
-SYS68K/CPU-33 [Joakim Larsson Edstrom]
-Time Crisis II (Japan, TSS1 Ver. B) [Bill D., The Dumping Union]
-Time Crisis II (US, TSS5 Ver. A) [Naoki, Smitdogg, The Dumping Union]
-Unicorn Dreaming (0101228V, New Zealand) [Heihachi_73]
-Wild Amazon (01J01996, Venezuela) [Heihachi_73]
-War: The Final Assault (Apr 7 1999) [CoolFox]
+Knights of Valour 3 HD (V101) [XingXing]
+Knights of Valour 3 HD (V102) [XingXing]
+Knights of Valour 3 HD (V103) [XingXing]
+Knights of Valour 3 HD (V104) [XingXing]
+Lost in Space (1.01 France) [PinMAME]
+Sega Rally Championship - DX (original rev) [Gerald COY]
+Terco 4426 CNC Programming station
+Top Skater (USA) [Gerald COY]
+Toshiba T1000 [shattered]
+Virtua Striker 2 '99 (Step 1.5) [Gerald COY]
+X-Files (3.03 France) [PinMAME]
 
 
 New WORKING software list additions
 -----------------------------------
-atom_flop.xml: Egghead in Space, F14 Tomcat [Nigel Barnes]
-bbcb_cass.xml: The Music System [Nigel Barnes]
-bbcb_flop.xml: various games, applications, utilities [Nigel Barnes]
-bbcb_flop_orig.xml: redumped Farm Management Suite double sided [Nigel Barnes]
-bbcmc_flop.xml: ALPS, Astro Blaster, Carnival [Nigel Barnes]
-megadriv.xml: Cool Spot (Euro, Prototype) [FakeShemp, Team Europe]
-pet_rom.xml: SUPER*TOOL [Francesco Messineo]
-pro128s_flop.xml: Disco Welcome [Nigel Barnes]
-snes.xml: Syvalion (Euro, Prototype) [FakeShemp, Team Europe]
-
-
-New NOT_WORKING software list additions
----------------------------------------
-archimedes.xml: RISC OS 3 Applications, many coverdisks and commercial applications [Nigel Barnes]
-bbc_flop_6502.xml: Hi-InterSheet, Hi-View, Hi-Wordwise+ [Nigel Barnes]
-electron_flop.xml: all known 5.25" DFS releases [Nigel Barnes]
-pico.xml:
- Cooking Pico (Jpn), Cooking Pico (Kor), Toy Story 2 (Kor), The Cloud is Wizard (Kor), Tago Galka (Kor), Dreamland Tour (Kor)
- [Team Europe]
-sawatte.xml: Doraemon Nobita no Dou Butsu Land, Soreike! Anpanman Onamae Na~ni, Ultra Hero Touch [Team Europe]
+apricot_flop.xml: Demonstration Pictures, MS-DOS 2.11 BIOS VR2.7, MS-DOS 2.11 BIOS VR3.1, QUEST - The Adventure [Dirk Best]
 
 
 Translations added or modified
 ------------------------------
-German [rootfather]
+Catalan [Jordi Mallach]
 
 
 Source Changes
 --------------
--imgtool: Various refactoring: [Nathan Woods]
- * Consolidated logic for default implementation of imgtool::image::list_partitions().
- * Changed imgtool::stream::open*() to return imgtool::stream::ptr.
- * Fixed a recently introduced bug that caused image types that do not support partitions to function incorrectly.
+-Created DYNAMIC_API macros for cleaner definition of dynamically linked functions. [Brad Hughes]
 
--core: Disassembler modernisation: [Nathan Woods]
- * Merged M6809, HD6309 and Konami disassemblers.
- * Added arcompact and PDP8 disassemblers to unidasm.
- * Fixed unidasm declaration for upd7725.
- * Eliminated static disassembly buffers in RSP, PowerPC and MIPS DRCs.
- * Changed all disassemblers to use output stream rather than character buffer.
- * Changed disassembler overrides to use 'std::ostream &' internally.
- * Changed disassembler infrastructure to not use char buffers internally.
+-Double-check key state before UI autorepeat (fixes github issue #1169). [Brad Hughes]
 
--apollo: Enabled creation when non-existent image name is supplied for omti8621 and sc499. [Hans Ostermeyer]
+-m68k: Respect 68020 "freeze I-cache" bit; micro20 68020 cache test now passes. [R. Belmont]
 
--sc499: Corrected regressions that prevented writing. [Hans Ostermeyer]
+-micro20: Hack to start up at MacsBug/shell entry point, added terminal and devices. [R. Belmont]
 
--various: Miscellaneous typo fixes. [Jordi Mallach, Tafoid]
+-i960: Added scanbyte and IP-relative lda opcodes, masked low bits of branch targets. [R. Belmont]
 
--arm, arm7: Various emulation improvements: [Sandro Ronco]
- * Implemented Transfers to User Bank in LDM/STM and fixed flags corruption in branch opcodes.
- * Fixed register-base shift with a value >= 32, this fixes the RISC OS graphics issues.
- * Fixed carry for ROR and preserve IRQ_MASK in LDR R15,***.
+-i960: Preliminary support for CALLS instruction and WIP on FAULTx instructions. [R. Belmont]
 
--mmodular, risc2500: Moved Saitek RISC 2500 into a separate driver and added internal layout and inputs. [Sandro Ronco]
+-archimds: Fixed sound double-buffering and playback frequency. [R. Belmont]
 
--a310: reworked HLE keyboard and added mouse input. [Sandro Ronco]
+-aristmk5: Added default NVRAM to US sets so the games come up in a playable state. [Heihachi_73, R. Belmont]
+ * cuckoou, dolphntru, incasunu, magimask, magimaska, partygrs, qnileu, wcougaru
 
--aristmk5: Various improvements: [Sandro Ronco]
- * Hooked up EEPROMs, UARTs and some inputs.
- * Fixed video DMA when vidstart != 0.
- * Added coin input, logic door input and RTC.
- * Fixed SRAM banking.
+-ppc: Set DSISR to the exception flags rather than the address on data access faults and correct flag values.
+ [R. Belmont, Vas Crabb, maximumspatium]
 
--archimds: Fixed horizontal display position and cursor position in VIDC. [Sandro Ronco]
+-DRC: Fixed XMM usage on SysV x64 ABI, restoring debugger functionality on Mac/Linux for DRC drivers.
+ [maximumspatium, R. Belmont, Ville Linde]
 
--atarigx2: Reverse-engineered Space Lords security FPGA and implemented decryption code.
- [Morten Shearman Kirkegaard, Samuel Neves, Peter Wilhelmsen]
+-Added preliminary MB86235 recompiler. [Ville Linde]
 
--atarigx2: Fixed inputs in Space Lords. [MASH]
+-delegates: Don't crash on late binding if no object is actually needed. [O. Galibert]
 
--ti99: Fixed save states and declared MACHINE_SUPPORTS_SAVE. [Michael Zapf]
+-pci9050: Fixed the mappings. [O. Galibert]
 
--midvunit: Renamed wargods CHD to reflect actual version on disk. [Ryan Holtz]
+-sharc: Use standard memory maps. [O. Galibert]
 
--hazeltin: Various initial changes: [Ryan Holtz]
- * Added keyboard hookup, but will need 8048 dumping or black-boxing.
- * Added preliminary video, still broken due to timing issues.
- * Added state-machine bipolar PROMs.
+-tms32025: Use the standard memory interfaces. [O. Galibert]
 
--core: Added non-netlist devices for logic ICs: [Ryan Holtz]
- * 54/74160,161,162,163
- * 54/7416x Hex/Quad D Flip-Flops with Clear
- * 9334/DM9334 8-Bit Addressable Latch
- * 7400 Quad 2-Input NAND Gate, 7404 Hex Inverter, 82S126/82S129 256x4-bit PROM
+-dimemory: Removed the magic bypass. [O. Galibert]
 
--sun4: Simplified DMA implementation. [Ryan Holtz]
+-votrax sc01: Simulate. [O. Galibert]
+ * Complete simulation of digital section based on die imaging
+ * Removed now-obsolete samples
+ * Plosives are still imperfect
 
--naomi: various naming changes: [MetalliC]
- * Added supported region info.
- * Changed all games to "Export name / Japan name" template.
- * Correct a few names as per title screens.
+-mc1000: Removed direct update handler. [O. Galibert]
 
--namcos12: Added Namco Cyber Lead cabinet JVS IO and LED controller PCB dumps. [PascalP, Team Europe]
+-tnzs: Various refactoring. [Ryan Holtz]
 
--aristmk6: Hooked up IRQ registers. [MetalliC]
+-netlist: Added simple ROM hookup capability. [Ryan Holtz]
 
--naomi: Added missing PICs for Dragon Treasure 2 main, Dragon Treasure 2 & 3 satellite, and WCCF 2001-2002.
- [Android, Darksoft, f205v, rtw, MetalliC]
+-netlist: Device additions: [Ryan Holtz]
+ * 74161 Synchronous 4-Bit Binary Counter with Clock
+ * 7473 Dual Master-Slave J-K Flip-Flops with Clear and Complementary Outputs
+ * Am2847 Quad 80-bit Static Shift Register
+ * DM9334 8-bit Addressable Latch
+ * 82S126 1K-bit bipolar PROM
+ * 74174 Hex D-Type Flip-Flop with Clear
+ * 2716 16 Kbit (2048x8) UV EPROM
+ * 74166 Parallel-Load 8-Bit Shift Register
+ * 74260 Dual 5-Input NOR Gate
+ * Intel 2102A 1Kbit (1024x1) Static RAM
+ * 74365 Hex Bus Driver with 3-State Outputs
+ * Generic 2- and 3-terminal Tristate device
+ * 74165, 74194, 7475, 7485, and DM9322
+ * 82S126 4kbit (512x8) TTL bipolar PROM
+ * 82S123 256-bit (32x8) TTL bipolar PROM
+ * Note: Tristate device and 74365 do not actually tristate, they are simply a way of combining multiple outputs/chip enables.
 
--luaengine: Converted to sol2. [Carl]
+-netlist: Added shared RAM pointer, for use by netlist RAM devices which need updating by non-netlist driver code. [Ryan Holtz]
 
--plugins/console: Added Lua console as plugin. [Carl]
+-netlist: Various fixes: [Ryan Holtz]
+ * 7473: Made device only transition on a falling clock.
+ * 74161: Inverted Clear and Clock inputs to match datasheet.
+ * 74260: Fixed number of inputs.
+ * Am2847: Fixed shift register size (was 160 bits, should have been 80 bits).
+ * DM9334: Inverted C and E inputs to match datasheet.
 
--core: Moved device_memory_interface from driver_device to dummy_space_device. [smf]
- * Exposed the dummy_space_device as machine().dummy_space() with a trampoline in driver_device for existing callers.
- * Debugger no longer needs to special case root_device() to avoid showing the dummy address space.
+-hazeltin: Added netlist-based video board emulation. [Ryan Holtz]
 
--taitogn: Various changes: [smf]
- * Implemented G-NET BIOS flashing
-   * Games that require the v2 BIOS now require you to update the BIOS and turn off JP1 as part of the installation
-   * A v1 BIOS flash is included, but you aren't forced to use it
- * Moved G-NET protection out of ATAFLASH and into individual devices for each type of card
- * Added build dates and times to G-NET game descriptions.
+-XML refactoring: [Vas Crabb]
+ * Moved stuff to namespace util::xml and scoped down some enums.
+ * Split config load/save delegate types, made config load take const node so it can't inadvertently mangle data.
 
--zn: Various changes: [smf]
- * Implemented enough analogue control reading on ZN1/ZN2 for RC De Go and Go By RC.
- * Fixed ZN1/ZN2 DIP switch descriptions.
+-coretmpl: Added an associative LRU cache with map-like behaviour. [Vas Crabb]
 
--Implemented S1985 backup RAM [smf]
- * Fixes TPC310 accessories cursor movement on the second time you launch it with left ctrl + left shift.
- * Fixed Matsushita backup RAM saving.
- * Implemented S1985 and Matsushita state saving.
- * Implemented MSX switched interface without using an address map.
+-selmenu: Use LRU cache so icons don't all need to be reloaded on scroll. [Vas Crabb]
 
--Fixed heap corruption when loading a new CHD fails. [smf]
+-uismall.bdf: Set default character for absent glyphs. [Vas Crabb]
 
--Throw CHDERR_FILE_NOT_WRITEABLE rather than CHDERR_UNSUPPORTED_VERSION if you try to open an old version CHD or writing. [smf]
+-rendfont.cpp: Fixes and Improvements: [Vas Crabb]
+ * Encapsulated many BDF and BDC file format handling details.
+ * Made file I/O 64-bit clean.
+ * Added some checks for allocation errors.
+ * Wrote more solid BDF parser with error messages and trace logging.
+ * Fixed heap smash when building bitmaps for BDF fonts.
+ * Extended BDC format to support high planes and default character.
+ * Render default character if glyph not found for BDF/BDC.
 
--darkmist: Video fixes: [Angelo Salese]
- * Added real transparent pen mixing from PROMs, fixes ranking screen and gameplay area in Dark Mist.
- * Fixed sprite-sprite priorities, sprite chip fetches from top to bottom.
+-Made bitmaps movable, allowing them to be used in vectors and emplaced easily. [Vas Crabb]
 
--saturn: Various changes: [Angelo Salese]
- * Worked around VDP1 timings in Sega Saturn, fixes regression with Batman Forever gameplay speed.
- * Added Rotation Parameter read control register, fixes at least Riddler stage ROZ positioning in Batman Forever.
+-Fixed uninitialised memory read as debugger command history (github #1802). [Vas Crabb]
 
--mirage: Added 93C46 EEPROM hook-up. [Angelo Salese]
+-netlist: Added new devices: [Vas Crabb]
+ * uA741 in 8-, 10- and 14-pin DIP variants
+ * 4316 bilateral switch pack
 
--seta: Added backup RAM hookup for kiwame, fixes "BACKUP RAM ERROR" at first boot. [Angelo Salese]
+-Amiga/Buddha: Cleanups and fixes, partially working now. [Dirk Best]
 
--ncr5390: Implemented selection disable. [O. Galibert]
+-Created an ef9369 device and used it for guab and mpu4vid. [Dirk Best]
 
--addrmap refactoring: [O. Galibert]
- * Removed device parameter
- * De-hand-templatized address_map_entry, remove then unneeded entry parameter
- * Simplified constructor, thanks Micko
- * Changed setters into passthroughs
- * Stream it
- * Changed to use dot syntax rather than -> syntax for chaining
+-guab: Cleanup and improvements: [Dirk Best]
+ * Hooked up SN76489 ready signal, hooked up some debug LEDs.
+ * Hooked up PPIs and ACIA.
+ * Labelled some outputs.
+ * Fixed and improved output labels, added ten up labels.
 
--addrmem: Made obvious renames and added helpers. [O. Galibert]
+-6840ptm: Use standard device clock for internal clock. [Dirk Best]
 
--general: Eliminated attaching memory maps to driver_device. [O. Galibert]
+-beezer: Rewrote driver. [Dirk Best]
+ * Uses the standard 6840 PTM core for sound generation
+ * New MM583 Noise Generator device
+ * New DAC-76 DAC sound
+ * Uses resistor network values for colors
+ * Uses bankdev device for banking
 
--emucore: Removed generic_ptr. [O. Galibert]
+-mcr68: Use standard 6840 PTM core, replacing custom implementation with the standard one. [Dirk Best]
 
--scn2674: Various changes: [Barry Rodewald]
- * Corrected the row on which a split occurs, fixes Octopus display of the last row before the status line split.
- * Added command 0xA6, fixes Octopus status line in Concurrent DOS, and BIOS character block write function.
+-zwackery: Removed Artificial Artist PAL, now included in the csd device. [Dirk Best]
 
--octopus: Various changes: [Barry Rodewald]
- * Added cursor display.
- * Added colour attributes.
- * Added blink and underline attributes.
- * Hooked up serial lines, Concurrent DOS can now use the first serial port as an extra terminal.
- * Fixed Z80 RAM banking past 256kB.
+-zwackery: Corrected ROM labels and locations. [Dirk Best]
 
--fmtowns: Addded support for IC Memory Card images. [Barry Rodewald]
- * Limited to 16MB in size until software that supports more can be found.
+-mcr68: Move zwackery to its own driver (doesn't have much in common with other games in driver). [Dirk Best]
+ * Also cleaned up implementation, made spriteram 8-bit, added some hardware info and added button descriptions.
 
--x68k: Added keyboard LEDs to layout display. [Barry Rodewald]
- * Among other things, this fixes the 'dancing keyboard' display when running Cotton.
+-Midway Cheap Squeak Deluxe sound board improvements: [Dirk Best]
+ * Moved to its own file and corrected its name.
+ * Updated interface to better reflect real hardware.
+ * Added address deocoding PAL and verified memory map.
 
--mac: Split 128/512/Plus into a new separate, more modern driver. [R. Belmont]
+-Identified DAC for Midway Cheap Squeak Deluxe/Turbo Cheap Squeak. [Dirk Best]
 
--mac: Corrected regression in IIvx/IIvi models. [R. Belmont]
+-apricot improvements: [Dirk Best]
+ * Fixed CTS polarity and marked as working - with the SIO fix the system is now very stable
+ * Fixed keyboard error 31, now displays 'System OK'
 
--apple2gs: Switched to use z80scc, added printer and modem ports. [R. Belmont]
+-z80dart: Only update serial line configuration if it actually changes. [Dirk Best]
+ * Allows the apricot serial port to work correctly.
 
--sdgndmps: Added DIP switch names and locations (verified from manual). [AJR]
+-pit8253: Reading back the count while in the middle of a 16-bit write returns a XOR'ed version of the value written. [Dirk Best]
+ * Fixes apricot error 29.
 
--pg685: Added pg675 and hooked up MM58167 RTC. [R. Belmont, rfka01]
+-fromance.cpp: Fixed OL gal display for nekkyoku. [Angelo Salese]
 
--pg685: Various changes: [R. Belmont]
- * Preliminary working oua11 video.
- * Fixed ROM and ROM shadow mapping for oua12 so it actually boots.
- * Preliminary not-quite-working oua12 video (chargen decode is unknown).
+-fromance.cpp: Added visible horizontal parameter to CRTC. [Angelo Salese]
 
--pg675, pg685: Added hardware info. [rfka01]
+-tail2nos.cpp improvements: [Angelo Salese]
+ * Added sound semaphore hookup, fixes random BGM lockups.
+ * Added alternative input method, selectable through control panel DIP switch.
+ * Added DIP switch locations.
 
--micro20: Added more device hookups, gets farther into POST. [R. Belmont]
+-srmp2.cpp: Fixed regression with ADPCM playback on m68k based games. [Angelo Salese]
 
--concept: Added optional MacsBug ROMs. [Al Kossow, R. Belmont]
+-neogeo: Corrected burningfpa romlabels (thanks jackc) and added it to software list. [hap]
 
--core: Fixed a bug parsing the software name option that prevented loading slot defaults for software selected from the internal
- UI. [AJR]
+-microtouch: Added output status command and fixed data transmission at 2400 baud. [Sandro Ronco]
 
--sh2dasm, sh4dasm: Changed the disassemblers to use 'std::ostream &' internally. [AJR]
+-aristmk5: Added internal layout and connected microtouch to magimask and partygrs. [Sandro Ronco]
 
--pit8253: Made MSB-only counter writes lower outputs in mode 0. [AJR]
+-Archimedes: Made floppies work. [Sandro Ronco]
 
--amusco: Various changes: [AJR]
- * Identified and hooked up 8155 interface chips for LPT and RTC.
- * Fixed PIT IRQs; game speed is much better now.
- * Coin inputs now read properly through IRQ4.
- * Promoted draw88pkr to WORKING (no more "COIN ERROR" on startup, though POST still fails memory test for some reason).
- * Removed spurious coin counter.
- * Updated notes on printer.
+-micro20: Added some features needed for the selftest, but couldn't hook up the missing parts so haven't verified that the self test
+ actually can run through now. [Joakim Larsson Edstrom]
+ * H4 is now cleared in reset and asserted by software down the line
+ * By calling the update_tin method the device now support external clock for the timer
+ * Clock can also be polled at port C bit #2
+ * The test expects something to pulse at port B and then a clock at TIN (port C pin #2 alternate function)
 
--seibu: Moved SEI80BU encryption out of the SEIBU_SOUND device and made it a device of its own. [AJR]
+-WIP: Intergraph driver support: Enabled more Rx interrupts and fixed error FIFO. [Joakim Larsson Edstrom]
 
--amusco: Added button-lamps and coin counter support. [Roberto Fresca]
+-WIP Apple Laser Writer II NT and some SCC improvements. [Joakim Larsson Edstrom]
 
--z80scc: Various changes: [Joakim Larsson Edstrom]
- * Added support for RTxC as BRG clock source, allows the SGI Indy to have a console.
- * Fixed a bug in rr15 support, allows macplus, etc. to boot now.
- * Improved interrupt handling, allows mouse pointer to move in macplus driver for System 6.0.8.
- * Fixed init state of latched rr0 values, improves the success ratio of getting the mouse working in both X and Y on macplus, etc.
- * Minimal sync/hunt support to enable System 7 to boot on macplus.
+-Prodigy: Added layout. [Joakim Larsson Edstrom]
 
--z80dart: Refactored FIFOs using new template based FIFO class. [Joakim Larsson Edstrom]
+-68230: Added bitwise update methods for all ports and moved register access methods to private section. [Joakim Larsson Edstrom]
 
--didact: Various Candela changes: [Joakim Larsson Edstrom]
- * Added can09, a non working driver for the Candela main computer, a 6809 based design with FDC and a 6850 CRTC.
- * Added can09t, a somewhat working driver for the Candela terminal, a slimmer version without FDC and with a terminal interface.
+-PIT68230: Fixed bug in port A-C write and added check of DDR registers for bit updates. [Joakim Larsson Edstrom]
 
--fccpu30: Various changes: [Joakim Larsson Edstrom]
- * Added new board variants as WIP: cpu30x, cpu30xa, cpu30za, cpu30zbe, cpu30be8, cpu30be16, cpu30lite4, cpu30lite8, cpu30senr,
-    cpu30senr501, cpu33
- * Added support for -ramsize according to each board variant.
- * Renamed roms to reflect on content and versions.
- * Mapped the Epson 72423 RTC device to the msm6242_device driver as it is compatible.
- * Added mock handlers with LOG info for devices that needs to be written.
- * Exposed possibility to turn off FPU in case it is not installed.
- * fccpu: Prepared to split out base fccpu class to support drivers for cpu2x and cpu4x boards etc.
- * Various small fixes to PIT68230, FGA022, DUSCC.
+-68230: Added initial support for timer interrupts and embryonic support for port interrupts. [Joakim Larsson Edstrom]
 
--prodigy: Added skeleton driver for ACI Destiny Prodigy chess computer. [Joakim Larsson Edstrom]
+-Fixed a regression FIFO bug and a bug in the handling of Special Interrupts. [Joakim Larsson Edstrom]
 
--z80sio, mzr8105: Added UPD7201 device type to and changed driver to use it. [Joakim Larsson Edstrom]
+-Fixed name to a better guess for MCU name for plump pop, and marked as bad pending verification that it is the same MCU which
+ drtoppel and extermination use. [Lord Nightmare]
 
--rax: Emulated the Acclaim RAX sound board, fixing sound in Batman Forever and NBA Jam Extreme. [Phil Bennett]
+-tnzs.cpp: Updated a slew of comments, added most missing PALs as undumped, fixed some ROM labels, added a chart of the different
+ Taito/Seta PCBs covered by tnzs.cpp and the differences between each. [Lord Nightmare]
 
--zn: Hooked up extra NVRAM in NBA Jam Extreme. [Phil Bennett]
+-toaplan1.cpp: Fixed DSWB reading (seems to be inverted when read by the MCU), also reverted changes to TJUMP jumper settings and
+ inverted those as well on read, though it still seems to be a bit screwy for some settings. [Lord Nightmare]
 
--bbc: Added ACP 1770 DFS to acorn1770 FDC. [Nigel Barnes]
+-toaplan1.cpp: vimana regions should work fine now. [Lord Nightmare]
 
--electron: Added PRES ADFS versions to Plus3 expansion. [Nigel Barnes]
+-Don't use mem_mask as ATA doesn't have an equivalent mechanism for byte accesses and it could mask out data that real hardware
+ would keep, instead fix issue with 68000 byte writes to sector count by only taking the bottom 8 bits from the bus. [smf]
 
--a310: Added new NOT WORKING machines Archimedes 305, Archimedes 440, Archimedes 3000, Archimedes 410/1, Archimedes 420/1,
- Archimedes 440/1, Archimedes 540, Acorn A5000, Acorn A4, Acorn A4000, Acorn A5000 Alpha [Nigel Barnes]
- * Renamed a310->aa310 to avoid conflict with Amiga machines.
- * Added all missing OS releases Arthur 0.30, RISC OS 2.01, RISC OS 3.00, RISC OS 3.10, RISC OS 3.19 (German).
- * Made all machines default to the OS (Arthur, RISC OS 2, RISC OS 3) they were shipped with.
- * Corrected ROM labels/locations.
- * Added default CMOS to boot to desktop.
- * Mapped Acorn A4 Power Management extension.
+-Fixed ATA Write Multiple (command c5) ignoring the block count on the first block. [smf]
 
--hp9845: Re-implemented 98035 module with a nanoprocessor driver. [F.Ulivi]
- * Now possible to emulate the 98035 RTC module at a low level thanks to firmware ROM dump from Mr. Kueckes.
- * Implemented "nanoprocessor" microcontroller CPU core and disassembler.
+-Update disassembly if IP or CS are changed in the debugger; also update IP and CS when PC or CURPC changes. [smf]
 
--hp9845: Implemented HP98034 module (HPIB interface). [F.Ulivi]
+-Added preliminary sound to Dulmont Magnum. [smf]
 
--quizpun2: Hooked up MCU, improved graphics and sound. [Luca Elia]
+-Added halt to debugger state, so you can break out of a hlt instruction. [smf]
 
--crystal: Fixed VRender0 timers. [Luca Elia]
+-HACK: return 0xffff for the current program counter while fetching the vector as the segag80r protection currently relies on it.
+ Reduce the number of extraneous reads that the segag80r protection performs. [smf]
 
--cedar_magnet: Preliminary magnet system sound and various flag fixes. [David Haywood]
+-Added multiplexed inputs for Beastie Feastie and Dealer. [smf]
 
--smskr: Added support for the seo-jin 11-in-1 multi-game bootleg cartridge. [David Haywood]
+-EPOS decryption simplification WIP. [smf]
 
--aristmk6: Various changes: [David Haywood]
- * Cleaned up ROM loading.
- * Show framebuffer? instead of debug viewer - can see startup text at least.
- * Extended ROM area so that the bigger games map properly and pass their checksums.
- * Corrected flamolce rom loading.
- * Corrected rumbreel rom loading and switch 1x and 2x IC positions, it passes test and is consistent with others now.
+-Use correct Commodore LCD font. [Mike Naberezny, smf]
 
--sh4: Began SH4 MMU improvements with a view to seeing what aristmk6 needs, allowed table upload by LDTLB opcode, allowed
- experimental MMU test code to be enabled/disabled on a per-driver basis. [David Haywood]
+-seta.cpp: Hooked up Zombie Raid NVRAM, added calibrated default. [MetalliC]
 
--core: Added delegate support for lambdas and std::functions in general, also supporting const members now. [Miodrag Milanovic]
+-stv.cpp: Documented IO chip, fixed astrass test mode hang. [MetalliC]
 
--aristmk5: Increased ROM window size for incasunu and geisha, fixing graphic CRC check and allowing incasunu to boot.
- [David Haywood]
+-Added Sega DIMM board architecture documentation. [MetalliC]
 
--core: Added more applicable Catch testing framework and converted all tests to be done properly by guidelines. [Miodrag Milanovic]
- * Still needs TESTS=1 to enable build of tests
+-amstrad.cpp: Caps Lock key does not have a physical toggle. [AJR]
 
--osd: Moved UWP asset files to proper place. [Miodrag Milanovic]
+-Added 'o' variants to memory debugging commands to request decrypted opcodes space. [AJR]
 
--util: Added a simple FIFO template. [Vas Crabb]
+-Created new 74LS157 device and hooked it up to MSM5205 on Rastan. [AJR]
 
--xmlfile: Turned API into something that looks like C++ and allowed use of const data node objects. [Vas Crabb]
+-d9final: Set initial banking so Z80 doesn't run off rails. [AJR]
 
--3rdparty: Updated LZMA to 16.04 (security and portability fixes). [Vas Crabb]
+-grainbow: Fixed palette dimming by respecting a fade-me-not bit. [AJR]
 
--core: Introduced u8/u16/u32/u64/s8/s16/s32/s64 alias types: [Vas Crabb]
- * New abbreviated types are in osd and util namespaces, and also in global namespace for things that #include "emu.h"
- * Removed the cstdint types from everything in emu.
- * Removed U64/S64 macros.
- * Fixed a bug in dps16 caused by incorrect use of macro.
- * Fixed debugcon not checking for "do " prefix case-insensitively.
- * Fixed a lot of messed up tabulation.
- * Changed many macros and constants to constexpr.
- * Fixed up many __names.
+-mustache.cpp: Flip screen improvements: [AJR]
+ * Fixed Y positions of flipped sprites.
+ * Added and implemented flip screen "Hard SW" as in Irem games.
+ * Corrected polarity of all DIP switches.
 
--complay.py: Rewrote to parse/minify layout XML - invalid XML in internal layouts now cause build failures. [Vas Crabb]
+-Attempt at fixing 8155 timer behavior so 8085 doesn't lose interrupts in equites. [AJR]
 
--uismall.bdf: Added some typographical characters to, including the hair space used by the internal UI. [Vas Crabb]
+-automat: Sound improvements: [AJR]
+ * Reduced YM2203 speed to match music pitch on reference video.
+ * Added second MSM5205 plus two 74LS157 and fixed communications.
+ * Added sound banking (probably not entirely correct).
 
--frontend: Encapsulated more of the menu base class to control when layout changes can happen, encapsulated mouse translation
- [Vas Crabb]
+-secretab: Incremental sound improvements: [AJR]
+ * Replaced one YM2203 with a YM3812.
+ * Added extra samples ROM to banked sound CPU region.
+ * Hooked up sound latch, enabling music and sound effects (still very imperfect).
+ * A little more PCB documentation.
+ * Added PCB locations to ROM names.
 
--osd: Fixed key names with -keyboardprovider win32 [Vas Crabb]
+-spangbl, pangba: 74LS157-ization and working sound. [AJR]
 
--core: Drop invalid input tokens when parsing configuration, fixes uncaught exception error when writing configuration. [Vas Crabb]
+-system16.cpp: Sound improvements for some bootlegs: [AJR]
+ * Hooked up MSM5205/74LS157 on the 2xYM2203 bootlegs, all of which now have some imperfect samples playback.
+ * Corrected goldnaxeb2 configuration to use the aforementioned sound system.
 
--hlsl: Fixed games with off-screen backdrop artworks (e.g. atarifb, bowler). [Jezze]
+-Fixed -romident misattributing device ROMs to alphabetically first driver using them. [AJR]
 
--sms: Various changes: [Enik Land]
- * Set initial audio mixing state on reset.
- * Documented the Sports Pad modes (and changed the default) used by Sports Pad Soccer (Jpn).
+-amusco.cpp: Added coin counter and dispenser device. [AJR]
 
--n64: Various changes: [Happy]
- * Only SP DMA skip for DRAM address, regardless of transfer direction.
- * Give priority to current transfer when reading AI length register.
- * Add delayed carry signal to AI (hardware bug allows carry signal from low to high to persist through a reload).
+-Dumped i8751 '317-0078' at location c2 for 'altbeast' set, added, works. [CAPS0ff]
 
--build: Fixed make VERBOSE=1 not showing archive commands for static libraries. [Happy]
+-Dumped i8751 '317-0123a' at location c2 for 'goldnaxe' set, added, works. [CAPS0ff]
 
--osd: Added new UWP icons/images. [JacKc]
+-Adaedd dump of i8751 '317-0112' at location c2 to 'goldnaxe2' set. [CAPS0ff]
+ * Chip was faulty, some bit errors, internal checksum fails - still using simulation for now.
 
--bionicc: Various changes: [Asayuki]
- * Added notes on clock frequencies and video signal timings.
- * Converted to raw screen parameters, correcting frame rate and vblank timing.
+-Added id8751h dumps to 'csilver' and 'srdarwin', not hooked up yet. [CAPS0ff]
 
--jangou: Corrected DIP switches for Jangou Lady. [system11]
+-tnzs: Added Taito M-Chip M-001 dump for extrmatn; also works for drtoppel and plumppop. [CAPS0ff]
 
--nbmj8891: Corrected DIP switches for Mahjong G-Men '89, Mahjong Vanilla Syndrome and Scandal Mahjong. [system11]
+-Added PIC16C57 dump to wbeachvl giving partial sound. [CAPS0ff]
+ * OKI banking setup for the game is incorrect so music doesn't currently play.
 
--nbmj9195: Corrected Pretty Sailor 18-kin DIP switches. [system11]
+-Decapped, deprotected, dumped and hooked up the hd647180X MCUs for Vimana, Fire Shark and Teki Paki. [CAPS0ff]
 
--tmnt: Changed back to 320x224 as per MT04790 discussion. [system11]
+-Decapped and read out security pics for umk3 and rmpgwt. [CAPS0ff]
+ * Added a new device type and bare bones loading, however communication with the main CPU is not hooked up yet.
 
--vigilant: Corrected visible screen area (PCB comparison). [system11]
+-Dumped PAL10H8 for Beastie Feastie (conversion kit). [Andrew Welburn, Craig Anstett]
 
--twincobr: Corrected ROM names for twincobr and twincobru. [system11]
+-Leave more comments on differences between 74107 and 74107A. [couriersud]
 
--tumbleb: Corrected Choky Choky OKI crystal, also corrected all games to mono as none use stereo PCBs. [system11]
+-netlist: Aligned naming of 9334 and made nl_hazelvid.cpp parseable by nltool. [couriersud]
 
--kaneko16: Unswapped button mappings for gtmr games so they match the PCB/manual. [system11]
+-imgtool refactoring: [Nathan Woods]
+ * Changed a number of declarations to use std::string instead of 'const char *'.
+ * Removed dead strncatz() function.
+ * Fixed a recently introduced error in the 'dir' command line command.
+ * Cleaned up the output of the 'dir' command.
 
--psikyosh: Corrected all games to mono as all games in this board family are mono. [system11]
+-DEC Rainbow 100 fixes: [Bavarese]
+ * Changed 7220 divider from 4 to 32 (closer to 1 Mhz from VT240).
+ * Stop flicker when color video is off.
+ * Changed the effect of GDC_MODE_ENABLE_VIDEO (see page 21 of PDF AA-AE36A).
+ * Addressed reentrance problems (reset procedure).
+ * Made scroll fully functional (deeper SCRAM levels and GDC diag test #9).
+ * Corrected cursor position in REGIS TSR.
+ * Implemented NMI for parity test.
+ * Fix aspect ratio in graphics modes.
+ * Fixed serial port A (printer port B needs more work.
+ * Added support all four ClikClok versions.
 
--marvland: Tagged as imperfect sound and needing redump of sound ROM. [system11]
- * The sound in this version does not match Japan or any of the ports, and sounds like incorrect sounds are being played.
+-konamigx: Fixed CPUs hanging on state load. [moralrecordings]
 
--aleck64: Added vivdolls DIP switches, digital joystick support needs adding, game is switchable. [system11]
+-Added floppy drives to the PG675 and PG685 variants, changed floppy controller to FD1797 (not hooked up yet).
 
--rainbow: Various Rainbow 100 changes: [Bavarese]
- * Fixed colors in highres mode and video levels.
- * Made a small fix to serial Rx.
- * Added support for hard disks with up to 17 sectors/track, as MFM controllers allow this.
- * Made port 50 readable (undocumented, yet used).
+-COP400 MCU fixes: [hap, Sean Riddle]
+ * L pins are tri-stated when EN2=0
+ * Corrected internal RAM memorymap for COP410
 
--upd7220: Fixed division by zero in update_graphics. [Bavarese]
+-Dumped 68705 a71_24.bin from Tokio/Scramble Formation. [ShouTime, brizzo]
 
--build: Fixed building on ppc64le and s390x. [Julian Sikorski]
+-Added fresh dump of exzisus (Magnet System) - one sector different, fixes graphical glitches in first level. [David Haywood]
 
--firebatl: Fixed music tempo. [ShouTime]
+-Started moving 68705 functionality to the CPU core rather than copy/pasted in all the drivers. [David Haywood]
 
--fidel6502: Redumped Par Excellence. [Berger]
+-Hooked up new 68705 dump to Tokio/Scramble Formation. [David Haywood]
 
--quizpun2: Dumped the 68705 MCU for "Quiz Punch", protected by an epoxy block. [Guru]
+-Sega DIMM security PICs update: [Jorge Valero, Android]
+ * Redumped PICs and documented S/Ns for: Quest of D, Key of Avalon 2.x, Virtua Striker 4 Ver.2006 (Japan).
+ * Dumped 253-5508-0364 from unknown NAOMI satellite game.
+ * Dumped 253-5508-0422J from Quest of D (some undumped newer version).
 
--sms_bootleg: Added the missing ROM to the smssgame set. [Astroblaster]
+-M1COMM/M2COMM cleanups and fixes [SailorSat]
 
--naomigd: Added unused/unknown security PIC dumps:
- * 253-5508-0352E some mahjong game? [mohamad "The Hedgehog" issawi, colour.thief]
- * 253-5508-0456J WCCF 2005-2006 Japan [any]
- * 253-5508-0506J unknown Chihiro [Android]
+-model1: Made wingwar360 playable. [SailorSat]
 
--lua: Added ability to show custom menu. [headkaze]
+-vaportra: Fixed missing game over animation, corrected 'P3 coin' and implemented irq6_ack. [darq]
 
--fds: Detached the other cart lists. [Reagan Roush]
+-yunsung8: Fixed MSM sounds, simplified inputs and changed incorrect cannballv manufacturer. [darq]
 
--zorba: Added software list for floppy disks as well as some documentation to the driver file. [Reagan Roush]
+-shootout: Fixed missing title screen music, fixed coin counter and simplified ROM loading. [darq]
 
--isbc: Added new isbc 286 rom version v1.0. [Al Kossow]
+-sidepckt: Fixed cocktail mode and added Y scroll. [darq]
 
--isbc_208: Added device. [Carl]
+-tecmo_mix: Fixed the saturated colors in Final Star Force (Level 2). [darq]
+
+-aristmk5: redumped chickna5u and topbana, now pass checksums. [Heihachi_73]
+
+-ccastles.cpp: Clarified input situation by assigning port conditions/names to the button inputs so they have proper default
+ mappings between Upright/Cocktail. [Tafoid]
+
+-New softlist: HP Integral PC. [shattered]
+
+-cps1.cpp: Added missing PAL dump to daimakai. [caius, Silvio Grazini]
+
+-aerofgt.cpp: Added correct and verified mask ROMs. [caius, The Dumping Union]
+ * Fixed size for U134 and U135 and added the redumped sound samples at U180 at the correct size.
+
+-debugimgui: Sort directory entries in mount dialog, as zippath_readdir() does not guarantee entries are in any particular order.
+ [Barry Rodewald]
+
+-stv redumps: [cpsystem3]
+ * Fixed bad dumps in Choro Q Hyper Racing 5.
+ * Redumped prc2ksu and prc28su using the heat-gun method to obtain valid dumps from fragile ROM chips.
+
+-Made phosphor persistence independent of frame rate. [anikom15]
+
+-Added proper support for Rescue on Fractalus (proto) - No Bankswitch, 2K Mirror RAM. [Mike Saarna]
+
+-metro.cpp: Made sound output mono for boards without stereo output. [system11]
+
+-nbmj8688.cpp: Corrected DIP switches for Camera Kozou. [system11]
+
+-hiscore.dat: Updates [Leezer]
+
+-Corrected labels for Midway PICs. [Guru]
+
+-de_2.cpp: Added missing sound ROM for uboat65. [PinMAME]
+
+-First stab at cleaning up the DOS boot and installation disk mess on the PC & AT softlists: [Justin Kerk]
+ * Removed 100% duplicate sets.
+ * Moved sets from ibm5170 to ibm5150 if they work on PC-class hardware (later DOS versions are needed for some games).
+ * Removed the ibm5160 softlist, it only contained one duplicate set.
+ * Added clone relationships.
+ * More consistency in set naming and metadata.
+
+-apple1.xml: Redumped dis-assembler. [Dagarman]

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/mame.git



More information about the Pkg-games-commits mailing list