summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--makefile14
-rw-r--r--src/emu/crsshair.c10
-rw-r--r--src/emu/devcb.c18
-rw-r--r--src/emu/devcb.h2
-rw-r--r--src/emu/device.c2
-rw-r--r--src/emu/device.h38
-rw-r--r--src/emu/emu.h29
-rw-r--r--src/emu/info.c100
-rw-r--r--src/emu/ioport.c6807
-rw-r--r--src/emu/ioport.h1930
-rw-r--r--src/emu/machine.c3
-rw-r--r--src/emu/machine/generic.c2
-rw-r--r--src/emu/machine/jvsdev.c2
-rw-r--r--src/emu/machine/microtch.c6
-rw-r--r--src/emu/memory.c22
-rw-r--r--src/emu/rendlay.c10
-rw-r--r--src/emu/screen.c11
-rw-r--r--src/emu/screen.h1
-rw-r--r--src/emu/sound/disc_cls.h2
-rw-r--r--src/emu/sound/disc_inp.c2
-rw-r--r--src/emu/ui.c56
-rw-r--r--src/emu/uiinput.c11
-rw-r--r--src/emu/uimain.c165
-rw-r--r--src/emu/uimain.h4
-rw-r--r--src/emu/uimenu.c2
-rw-r--r--src/emu/validity.c117
-rw-r--r--src/emu/validity.h6
-rw-r--r--src/emu/video/pc_cga.c8
-rw-r--r--src/ldplayer/ldplayer.c4
-rw-r--r--src/mame/audio/8080bw.c4
-rw-r--r--src/mame/audio/atarijsa.c16
-rw-r--r--src/mame/audio/cchasm.c8
-rw-r--r--src/mame/audio/cyberbal.c4
-rw-r--r--src/mame/audio/harddriv.c2
-rw-r--r--src/mame/audio/mario.c4
-rw-r--r--src/mame/audio/micro3d.c2
-rw-r--r--src/mame/audio/midway.c2
-rw-r--r--src/mame/audio/mw8080bw.c4
-rw-r--r--src/mame/audio/suna8.c2
-rw-r--r--src/mame/drivers/2mindril.c6
-rw-r--r--src/mame/drivers/30test.c8
-rw-r--r--src/mame/drivers/39in1.c2
-rw-r--r--src/mame/drivers/3do.c2
-rw-r--r--src/mame/drivers/40love.c2
-rw-r--r--src/mame/drivers/5clown.c8
-rw-r--r--src/mame/drivers/8080bw.c4
-rw-r--r--src/mame/drivers/ace.c2
-rw-r--r--src/mame/drivers/acefruit.c22
-rw-r--r--src/mame/drivers/acommand.c4
-rw-r--r--src/mame/drivers/actfancr.c12
-rw-r--r--src/mame/drivers/adp.c34
-rw-r--r--src/mame/drivers/aeroboto.c2
-rw-r--r--src/mame/drivers/airbustr.c36
-rw-r--r--src/mame/drivers/albazg.c62
-rw-r--r--src/mame/drivers/aleck64.c6
-rw-r--r--src/mame/drivers/alg.c10
-rw-r--r--src/mame/drivers/alpha68k.c88
-rw-r--r--src/mame/drivers/ampoker2.c24
-rw-r--r--src/mame/drivers/amspdwy.c6
-rw-r--r--src/mame/drivers/angelkds.c6
-rw-r--r--src/mame/drivers/aquarium.c2
-rw-r--r--src/mame/drivers/arabian.c2
-rw-r--r--src/mame/drivers/arcadecl.c4
-rw-r--r--src/mame/drivers/aristmk4.c28
-rw-r--r--src/mame/drivers/aristmk5.c4
-rw-r--r--src/mame/drivers/arkanoid.c2
-rw-r--r--src/mame/drivers/armedf.c16
-rw-r--r--src/mame/drivers/artmagic.c2
-rw-r--r--src/mame/drivers/asterix.c2
-rw-r--r--src/mame/drivers/asteroid.c16
-rw-r--r--src/mame/drivers/astinvad.c6
-rw-r--r--src/mame/drivers/astrocde.c6
-rw-r--r--src/mame/drivers/astrocorp.c2
-rw-r--r--src/mame/drivers/astrof.c28
-rw-r--r--src/mame/drivers/asuka.c34
-rw-r--r--src/mame/drivers/atarifb.c6
-rw-r--r--src/mame/drivers/atarig1.c12
-rw-r--r--src/mame/drivers/atarig42.c8
-rw-r--r--src/mame/drivers/atarigt.c12
-rw-r--r--src/mame/drivers/atarigx2.c14
-rw-r--r--src/mame/drivers/atarisy1.c32
-rw-r--r--src/mame/drivers/atarisy2.c30
-rw-r--r--src/mame/drivers/atarisy4.c10
-rw-r--r--src/mame/drivers/ataxx.c8
-rw-r--r--src/mame/drivers/atetris.c2
-rw-r--r--src/mame/drivers/attckufo.c4
-rw-r--r--src/mame/drivers/avalnche.c2
-rw-r--r--src/mame/drivers/aztarac.c4
-rw-r--r--src/mame/drivers/backfire.c16
-rw-r--r--src/mame/drivers/badlands.c14
-rw-r--r--src/mame/drivers/bagman.c8
-rw-r--r--src/mame/drivers/balsente.c2
-rw-r--r--src/mame/drivers/baraduke.c14
-rw-r--r--src/mame/drivers/batman.c4
-rw-r--r--src/mame/drivers/battlane.c2
-rw-r--r--src/mame/drivers/battlera.c10
-rw-r--r--src/mame/drivers/bbusters.c6
-rw-r--r--src/mame/drivers/beaminv.c2
-rw-r--r--src/mame/drivers/beathead.c2
-rw-r--r--src/mame/drivers/berzerk.c10
-rw-r--r--src/mame/drivers/bfcobra.c4
-rw-r--r--src/mame/drivers/bfm_sc1.c6
-rw-r--r--src/mame/drivers/bfm_sc2.c16
-rw-r--r--src/mame/drivers/bfm_sc4h.c4
-rw-r--r--src/mame/drivers/big10.c6
-rw-r--r--src/mame/drivers/bigevglf.c6
-rw-r--r--src/mame/drivers/bionicc.c6
-rw-r--r--src/mame/drivers/bladestl.c2
-rw-r--r--src/mame/drivers/blitz.c8
-rw-r--r--src/mame/drivers/blitz68k.c22
-rw-r--r--src/mame/drivers/blktiger.c2
-rw-r--r--src/mame/drivers/blmbycar.c4
-rw-r--r--src/mame/drivers/blockade.c16
-rw-r--r--src/mame/drivers/bloodbro.c6
-rw-r--r--src/mame/drivers/blstroid.c6
-rw-r--r--src/mame/drivers/bmcbowl.c8
-rw-r--r--src/mame/drivers/bnstars.c12
-rw-r--r--src/mame/drivers/bogeyman.c2
-rw-r--r--src/mame/drivers/boogwing.c2
-rw-r--r--src/mame/drivers/boxer.c20
-rw-r--r--src/mame/drivers/brkthru.c2
-rw-r--r--src/mame/drivers/bsktball.c2
-rw-r--r--src/mame/drivers/btime.c20
-rw-r--r--src/mame/drivers/bwidow.c6
-rw-r--r--src/mame/drivers/bwing.c18
-rw-r--r--src/mame/drivers/bzone.c6
-rw-r--r--src/mame/drivers/cabal.c16
-rw-r--r--src/mame/drivers/calchase.c12
-rw-r--r--src/mame/drivers/calomega.c24
-rw-r--r--src/mame/drivers/canyon.c8
-rw-r--r--src/mame/drivers/capbowl.c10
-rw-r--r--src/mame/drivers/cave.c50
-rw-r--r--src/mame/drivers/cb2001.c32
-rw-r--r--src/mame/drivers/cbasebal.c2
-rw-r--r--src/mame/drivers/cbuster.c8
-rw-r--r--src/mame/drivers/ccastles.c4
-rw-r--r--src/mame/drivers/cchance.c2
-rw-r--r--src/mame/drivers/cd32.c2
-rw-r--r--src/mame/drivers/cdi.c20
-rw-r--r--src/mame/drivers/centiped.c22
-rw-r--r--src/mame/drivers/cesclass.c2
-rw-r--r--src/mame/drivers/cham24.c8
-rw-r--r--src/mame/drivers/champbwl.c4
-rw-r--r--src/mame/drivers/chanbara.c2
-rw-r--r--src/mame/drivers/chance32.c2
-rw-r--r--src/mame/drivers/changela.c12
-rw-r--r--src/mame/drivers/chinagat.c4
-rw-r--r--src/mame/drivers/chinsan.c24
-rw-r--r--src/mame/drivers/chqflag.c4
-rw-r--r--src/mame/drivers/cinemat.c18
-rw-r--r--src/mame/drivers/circus.c10
-rw-r--r--src/mame/drivers/cischeat.c42
-rw-r--r--src/mame/drivers/citycon.c2
-rw-r--r--src/mame/drivers/clayshoo.c14
-rw-r--r--src/mame/drivers/cliffhgr.c6
-rw-r--r--src/mame/drivers/cloak.c2
-rw-r--r--src/mame/drivers/cloud9.c2
-rw-r--r--src/mame/drivers/clshroad.c8
-rw-r--r--src/mame/drivers/cmmb.c6
-rw-r--r--src/mame/drivers/cninja.c14
-rw-r--r--src/mame/drivers/cntsteer.c6
-rw-r--r--src/mame/drivers/combatsc.c6
-rw-r--r--src/mame/drivers/compgolf.c2
-rw-r--r--src/mame/drivers/coolpool.c14
-rw-r--r--src/mame/drivers/cop01.c2
-rw-r--r--src/mame/drivers/copsnrob.c6
-rw-r--r--src/mame/drivers/corona.c12
-rw-r--r--src/mame/drivers/cosmic.c16
-rw-r--r--src/mame/drivers/cps1.c80
-rw-r--r--src/mame/drivers/cps2.c8
-rw-r--r--src/mame/drivers/cps3.c4
-rw-r--r--src/mame/drivers/crbaloon.c4
-rw-r--r--src/mame/drivers/crgolf.c4
-rw-r--r--src/mame/drivers/crshrace.c8
-rw-r--r--src/mame/drivers/crystal.c10
-rw-r--r--src/mame/drivers/cshooter.c2
-rw-r--r--src/mame/drivers/csplayh5.c10
-rw-r--r--src/mame/drivers/cubeqst.c4
-rw-r--r--src/mame/drivers/cvs.c17
-rw-r--r--src/mame/drivers/cyberbal.c8
-rw-r--r--src/mame/drivers/cybertnk.c16
-rw-r--r--src/mame/drivers/dai3wksi.c2
-rw-r--r--src/mame/drivers/dambustr.c16
-rw-r--r--src/mame/drivers/darius.c10
-rw-r--r--src/mame/drivers/darkhors.c4
-rw-r--r--src/mame/drivers/darkseal.c8
-rw-r--r--src/mame/drivers/dassault.c20
-rw-r--r--src/mame/drivers/dblewing.c16
-rw-r--r--src/mame/drivers/dcheese.c2
-rw-r--r--src/mame/drivers/dday.c16
-rw-r--r--src/mame/drivers/ddealer.c2
-rw-r--r--src/mame/drivers/ddenlovr.c206
-rw-r--r--src/mame/drivers/ddragon.c18
-rw-r--r--src/mame/drivers/ddragon3.c10
-rw-r--r--src/mame/drivers/deadang.c4
-rw-r--r--src/mame/drivers/dec0.c14
-rw-r--r--src/mame/drivers/dec8.c56
-rw-r--r--src/mame/drivers/deco156.c6
-rw-r--r--src/mame/drivers/deco32.c50
-rw-r--r--src/mame/drivers/deco_ld.c4
-rw-r--r--src/mame/drivers/deco_mlc.c2
-rw-r--r--src/mame/drivers/decocass.c6
-rw-r--r--src/mame/drivers/deshoros.c6
-rw-r--r--src/mame/drivers/destroyr.c8
-rw-r--r--src/mame/drivers/dgpix.c4
-rw-r--r--src/mame/drivers/dietgo.c2
-rw-r--r--src/mame/drivers/discoboy.c2
-rw-r--r--src/mame/drivers/djboy.c14
-rw-r--r--src/mame/drivers/djmain.c48
-rw-r--r--src/mame/drivers/dkong.c30
-rw-r--r--src/mame/drivers/dlair.c34
-rw-r--r--src/mame/drivers/dmndrby.c32
-rw-r--r--src/mame/drivers/dogfgt.c2
-rw-r--r--src/mame/drivers/dooyong.c82
-rw-r--r--src/mame/drivers/dragrace.c10
-rw-r--r--src/mame/drivers/dribling.c6
-rw-r--r--src/mame/drivers/drw80pkr.c2
-rw-r--r--src/mame/drivers/dunhuang.c22
-rw-r--r--src/mame/drivers/dwarfd.c2
-rw-r--r--src/mame/drivers/dynax.c98
-rw-r--r--src/mame/drivers/dynduke.c6
-rw-r--r--src/mame/drivers/embargo.c10
-rw-r--r--src/mame/drivers/enigma2.c10
-rw-r--r--src/mame/drivers/eolith.c12
-rw-r--r--src/mame/drivers/eolith16.c4
-rw-r--r--src/mame/drivers/eprom.c10
-rw-r--r--src/mame/drivers/equites.c4
-rw-r--r--src/mame/drivers/ertictac.c42
-rw-r--r--src/mame/drivers/esd16.c26
-rw-r--r--src/mame/drivers/esripsys.c16
-rw-r--r--src/mame/drivers/ettrivia.c2
-rw-r--r--src/mame/drivers/exerion.c4
-rw-r--r--src/mame/drivers/exidy.c46
-rw-r--r--src/mame/drivers/exidy440.c6
-rw-r--r--src/mame/drivers/exprraid.c38
-rw-r--r--src/mame/drivers/exterm.c4
-rw-r--r--src/mame/drivers/f-32.c4
-rw-r--r--src/mame/drivers/f1gp.c14
-rw-r--r--src/mame/drivers/famibox.c8
-rw-r--r--src/mame/drivers/fantland.c112
-rw-r--r--src/mame/drivers/fcombat.c4
-rw-r--r--src/mame/drivers/feversoc.c2
-rw-r--r--src/mame/drivers/fgoal.c4
-rw-r--r--src/mame/drivers/finalizr.c2
-rw-r--r--src/mame/drivers/firebeat.c16
-rw-r--r--src/mame/drivers/firefox.c6
-rw-r--r--src/mame/drivers/firetrap.c6
-rw-r--r--src/mame/drivers/firetrk.c20
-rw-r--r--src/mame/drivers/flkatck.c6
-rw-r--r--src/mame/drivers/flyball.c10
-rw-r--r--src/mame/drivers/foodf.c4
-rw-r--r--src/mame/drivers/forte2.c2
-rw-r--r--src/mame/drivers/freekick.c2
-rw-r--r--src/mame/drivers/fromanc2.c18
-rw-r--r--src/mame/drivers/fromance.c10
-rw-r--r--src/mame/drivers/funkball.c16
-rw-r--r--src/mame/drivers/funkybee.c2
-rw-r--r--src/mame/drivers/funkyjet.c2
-rw-r--r--src/mame/drivers/fuukifg3.c8
-rw-r--r--src/mame/drivers/gaelco2.c8
-rw-r--r--src/mame/drivers/gaelco3d.c8
-rw-r--r--src/mame/drivers/galaga.c134
-rw-r--r--src/mame/drivers/galastrm.c4
-rw-r--r--src/mame/drivers/galaxia.c2
-rw-r--r--src/mame/drivers/galaxian.c20
-rw-r--r--src/mame/drivers/galaxold.c28
-rw-r--r--src/mame/drivers/galdrvr.c78
-rw-r--r--src/mame/drivers/galivan.c2
-rw-r--r--src/mame/drivers/galpani3.c2
-rw-r--r--src/mame/drivers/gameplan.c2
-rw-r--r--src/mame/drivers/gauntlet.c8
-rw-r--r--src/mame/drivers/gcpinbal.c6
-rw-r--r--src/mame/drivers/gei.c16
-rw-r--r--src/mame/drivers/gijoe.c2
-rw-r--r--src/mame/drivers/gladiatr.c14
-rw-r--r--src/mame/drivers/go2000.c16
-rw-r--r--src/mame/drivers/goal92.c10
-rw-r--r--src/mame/drivers/goldnpkr.c16
-rw-r--r--src/mame/drivers/goldstar.c444
-rw-r--r--src/mame/drivers/gomoku.c2
-rw-r--r--src/mame/drivers/goodejan.c10
-rw-r--r--src/mame/drivers/gottlieb.c28
-rw-r--r--src/mame/drivers/gpworld.c4
-rw-r--r--src/mame/drivers/grchamp.c2
-rw-r--r--src/mame/drivers/gridlee.c4
-rw-r--r--src/mame/drivers/groundfx.c4
-rw-r--r--src/mame/drivers/gstream.c12
-rw-r--r--src/mame/drivers/gsword.c14
-rw-r--r--src/mame/drivers/gticlub.c14
-rw-r--r--src/mame/drivers/guab.c2
-rw-r--r--src/mame/drivers/gunbustr.c4
-rw-r--r--src/mame/drivers/gundealr.c6
-rw-r--r--src/mame/drivers/gunpey.c10
-rw-r--r--src/mame/drivers/halleys.c8
-rw-r--r--src/mame/drivers/hanaawas.c8
-rw-r--r--src/mame/drivers/harddriv.c14
-rw-r--r--src/mame/drivers/highvdeo.c8
-rw-r--r--src/mame/drivers/hitme.c6
-rw-r--r--src/mame/drivers/hitpoker.c2
-rw-r--r--src/mame/drivers/hnayayoi.c2
-rw-r--r--src/mame/drivers/hng64.c34
-rw-r--r--src/mame/drivers/homedata.c12
-rw-r--r--src/mame/drivers/hornet.c8
-rw-r--r--src/mame/drivers/hvyunit.c42
-rw-r--r--src/mame/drivers/icecold.c6
-rw-r--r--src/mame/drivers/igs009.c10
-rw-r--r--src/mame/drivers/igs011.c48
-rw-r--r--src/mame/drivers/igs017.c156
-rw-r--r--src/mame/drivers/igspoker.c2
-rw-r--r--src/mame/drivers/imolagp.c2
-rw-r--r--src/mame/drivers/irobot.c2
-rw-r--r--src/mame/drivers/itech32.c28
-rw-r--r--src/mame/drivers/itech8.c2
-rw-r--r--src/mame/drivers/jack.c20
-rw-r--r--src/mame/drivers/jackal.c2
-rw-r--r--src/mame/drivers/jackpool.c28
-rw-r--r--src/mame/drivers/jaguar.c8
-rw-r--r--src/mame/drivers/jalmah.c50
-rw-r--r--src/mame/drivers/jangou.c22
-rw-r--r--src/mame/drivers/jantotsu.c8
-rw-r--r--src/mame/drivers/jchan.c34
-rw-r--r--src/mame/drivers/jedi.c6
-rw-r--r--src/mame/drivers/jongkyo.c36
-rw-r--r--src/mame/drivers/jpmimpct.c34
-rw-r--r--src/mame/drivers/jpmsys5.c8
-rw-r--r--src/mame/drivers/kaneko16.c26
-rw-r--r--src/mame/drivers/karnov.c10
-rw-r--r--src/mame/drivers/kas89.c20
-rw-r--r--src/mame/drivers/kingdrby.c14
-rw-r--r--src/mame/drivers/kingobox.c2
-rw-r--r--src/mame/drivers/kinst.c6
-rw-r--r--src/mame/drivers/klax.c4
-rw-r--r--src/mame/drivers/koikoi.c4
-rw-r--r--src/mame/drivers/konamigq.c2
-rw-r--r--src/mame/drivers/konamigv.c4
-rw-r--r--src/mame/drivers/konamigx.c14
-rw-r--r--src/mame/drivers/kongambl.c4
-rw-r--r--src/mame/drivers/kopunch.c2
-rw-r--r--src/mame/drivers/ksys573.c30
-rw-r--r--src/mame/drivers/ladybug.c16
-rw-r--r--src/mame/drivers/laserbat.c8
-rw-r--r--src/mame/drivers/lastfght.c6
-rw-r--r--src/mame/drivers/lazercmd.c10
-rw-r--r--src/mame/drivers/leland.c26
-rw-r--r--src/mame/drivers/lemmings.c16
-rw-r--r--src/mame/drivers/lethal.c6
-rw-r--r--src/mame/drivers/lethalj.c2
-rw-r--r--src/mame/drivers/liberate.c20
-rw-r--r--src/mame/drivers/liberatr.c10
-rw-r--r--src/mame/drivers/limenko.c4
-rw-r--r--src/mame/drivers/lockon.c8
-rw-r--r--src/mame/drivers/looping.c2
-rw-r--r--src/mame/drivers/lordgun.c6
-rw-r--r--src/mame/drivers/lvcards.c2
-rw-r--r--src/mame/drivers/m10.c12
-rw-r--r--src/mame/drivers/m107.c4
-rw-r--r--src/mame/drivers/m14.c4
-rw-r--r--src/mame/drivers/m63.c8
-rw-r--r--src/mame/drivers/m72.c22
-rw-r--r--src/mame/drivers/m79amb.c10
-rw-r--r--src/mame/drivers/macs.c30
-rw-r--r--src/mame/drivers/madalien.c2
-rw-r--r--src/mame/drivers/madmotor.c2
-rw-r--r--src/mame/drivers/magic10.c10
-rw-r--r--src/mame/drivers/magicfly.c10
-rw-r--r--src/mame/drivers/magtouch.c2
-rw-r--r--src/mame/drivers/majorpkr.c12
-rw-r--r--src/mame/drivers/malzak.c6
-rw-r--r--src/mame/drivers/mappy.c120
-rw-r--r--src/mame/drivers/marinedt.c2
-rw-r--r--src/mame/drivers/matmania.c2
-rw-r--r--src/mame/drivers/maxaflex.c6
-rw-r--r--src/mame/drivers/maygay1b.c6
-rw-r--r--src/mame/drivers/maygayv1.c4
-rw-r--r--src/mame/drivers/mayumi.c2
-rw-r--r--src/mame/drivers/mazerbla.c2
-rw-r--r--src/mame/drivers/mcatadv.c24
-rw-r--r--src/mame/drivers/mcr.c28
-rw-r--r--src/mame/drivers/mcr3.c30
-rw-r--r--src/mame/drivers/mcr68.c36
-rw-r--r--src/mame/drivers/mediagx.c10
-rw-r--r--src/mame/drivers/megadrvb.c10
-rw-r--r--src/mame/drivers/megasys1.c18
-rw-r--r--src/mame/drivers/megatech.c2
-rw-r--r--src/mame/drivers/meijinsn.c12
-rw-r--r--src/mame/drivers/merit.c4
-rw-r--r--src/mame/drivers/meritm.c2
-rw-r--r--src/mame/drivers/metlclsh.c2
-rw-r--r--src/mame/drivers/metro.c18
-rw-r--r--src/mame/drivers/mexico86.c2
-rw-r--r--src/mame/drivers/meyc8080.c8
-rw-r--r--src/mame/drivers/meyc8088.c10
-rw-r--r--src/mame/drivers/mgolf.c12
-rw-r--r--src/mame/drivers/midas.c4
-rw-r--r--src/mame/drivers/midvunit.c8
-rw-r--r--src/mame/drivers/midzeus.c10
-rw-r--r--src/mame/drivers/mirage.c12
-rw-r--r--src/mame/drivers/mirax.c2
-rw-r--r--src/mame/drivers/missile.c10
-rw-r--r--src/mame/drivers/mitchell.c32
-rw-r--r--src/mame/drivers/mjkjidai.c4
-rw-r--r--src/mame/drivers/mjsister.c4
-rw-r--r--src/mame/drivers/mlanding.c22
-rw-r--r--src/mame/drivers/model1.c4
-rw-r--r--src/mame/drivers/model2.c8
-rw-r--r--src/mame/drivers/model3.c38
-rw-r--r--src/mame/drivers/moo.c2
-rw-r--r--src/mame/drivers/mpoker.c2
-rw-r--r--src/mame/drivers/mpu3.c10
-rw-r--r--src/mame/drivers/mpu4.c8
-rw-r--r--src/mame/drivers/mpu4vid.c46
-rw-r--r--src/mame/drivers/mquake.c2
-rw-r--r--src/mame/drivers/ms32.c20
-rw-r--r--src/mame/drivers/msisaac.c2
-rw-r--r--src/mame/drivers/mugsmash.c8
-rw-r--r--src/mame/drivers/multigam.c6
-rw-r--r--src/mame/drivers/mw18w.c32
-rw-r--r--src/mame/drivers/mw8080bw.c262
-rw-r--r--src/mame/drivers/mwarr.c2
-rw-r--r--src/mame/drivers/mystston.c2
-rw-r--r--src/mame/drivers/mystwarr.c10
-rw-r--r--src/mame/drivers/namcofl.c14
-rw-r--r--src/mame/drivers/namcona1.c10
-rw-r--r--src/mame/drivers/namconb1.c32
-rw-r--r--src/mame/drivers/namcos1.c2
-rw-r--r--src/mame/drivers/namcos10.c2
-rw-r--r--src/mame/drivers/namcos11.c36
-rw-r--r--src/mame/drivers/namcos12.c18
-rw-r--r--src/mame/drivers/namcos21.c4
-rw-r--r--src/mame/drivers/namcos22.c58
-rw-r--r--src/mame/drivers/namcos23.c20
-rw-r--r--src/mame/drivers/namcos86.c32
-rw-r--r--src/mame/drivers/naomi.c2
-rw-r--r--src/mame/drivers/naughtyb.c12
-rw-r--r--src/mame/drivers/nbmj9195.c74
-rw-r--r--src/mame/drivers/nemesis.c20
-rw-r--r--src/mame/drivers/neodrvr.c4
-rw-r--r--src/mame/drivers/neogeo.c18
-rw-r--r--src/mame/drivers/nexus3d.c2
-rw-r--r--src/mame/drivers/nightgal.c36
-rw-r--r--src/mame/drivers/ninjakd2.c58
-rw-r--r--src/mame/drivers/nitedrvr.c2
-rw-r--r--src/mame/drivers/niyanpai.c30
-rw-r--r--src/mame/drivers/nmg5.c32
-rw-r--r--src/mame/drivers/nmk16.c12
-rw-r--r--src/mame/drivers/nova2001.c8
-rw-r--r--src/mame/drivers/nwk-tr.c18
-rw-r--r--src/mame/drivers/nycaptor.c4
-rw-r--r--src/mame/drivers/nyny.c6
-rw-r--r--src/mame/drivers/offtwall.c4
-rw-r--r--src/mame/drivers/ojankohs.c46
-rw-r--r--src/mame/drivers/omegrace.c2
-rw-r--r--src/mame/drivers/oneshot.c2
-rw-r--r--src/mame/drivers/onetwo.c6
-rw-r--r--src/mame/drivers/opwolf.c16
-rw-r--r--src/mame/drivers/orbit.c2
-rw-r--r--src/mame/drivers/othldrby.c2
-rw-r--r--src/mame/drivers/othunder.c2
-rw-r--r--src/mame/drivers/overdriv.c2
-rw-r--r--src/mame/drivers/pachifev.c4
-rw-r--r--src/mame/drivers/pacland.c4
-rw-r--r--src/mame/drivers/pacman.c12
-rw-r--r--src/mame/drivers/paradise.c12
-rw-r--r--src/mame/drivers/pastelg.c20
-rw-r--r--src/mame/drivers/pcat_nit.c2
-rw-r--r--src/mame/drivers/pcxt.c4
-rw-r--r--src/mame/drivers/pengadvb.c4
-rw-r--r--src/mame/drivers/peplus.c12
-rw-r--r--src/mame/drivers/peyper.c4
-rw-r--r--src/mame/drivers/pgm.c2
-rw-r--r--src/mame/drivers/phoenix.c30
-rw-r--r--src/mame/drivers/pingpong.c14
-rw-r--r--src/mame/drivers/pinkiri8.c20
-rw-r--r--src/mame/drivers/pipedrm.c2
-rw-r--r--src/mame/drivers/pktgaldx.c2
-rw-r--r--src/mame/drivers/playch10.c140
-rw-r--r--src/mame/drivers/playmark.c34
-rw-r--r--src/mame/drivers/plygonet.c6
-rw-r--r--src/mame/drivers/pntnpuzl.c10
-rw-r--r--src/mame/drivers/polepos.c8
-rw-r--r--src/mame/drivers/polyplay.c2
-rw-r--r--src/mame/drivers/poolshrk.c6
-rw-r--r--src/mame/drivers/popeye.c4
-rw-r--r--src/mame/drivers/popper.c16
-rw-r--r--src/mame/drivers/powerbal.c58
-rw-r--r--src/mame/drivers/prehisle.c2
-rw-r--r--src/mame/drivers/progolf.c10
-rw-r--r--src/mame/drivers/psikyo.c28
-rw-r--r--src/mame/drivers/psikyo4.c16
-rw-r--r--src/mame/drivers/psikyosh.c8
-rw-r--r--src/mame/drivers/pushman.c4
-rw-r--r--src/mame/drivers/pzletime.c2
-rw-r--r--src/mame/drivers/qdrmfgp.c2
-rw-r--r--src/mame/drivers/quantum.c6
-rw-r--r--src/mame/drivers/quasar.c12
-rw-r--r--src/mame/drivers/quizpani.c64
-rw-r--r--src/mame/drivers/raiden.c6
-rw-r--r--src/mame/drivers/rainbow.c32
-rw-r--r--src/mame/drivers/rallyx.c48
-rw-r--r--src/mame/drivers/rampart.c6
-rw-r--r--src/mame/drivers/re900.c18
-rw-r--r--src/mame/drivers/realbrk.c54
-rw-r--r--src/mame/drivers/redalert.c6
-rw-r--r--src/mame/drivers/redclash.c4
-rw-r--r--src/mame/drivers/relief.c4
-rw-r--r--src/mame/drivers/renegade.c2
-rw-r--r--src/mame/drivers/rltennis.c6
-rw-r--r--src/mame/drivers/rmhaihai.c4
-rw-r--r--src/mame/drivers/rohga.c8
-rw-r--r--src/mame/drivers/rollrace.c2
-rw-r--r--src/mame/drivers/route16.c8
-rw-r--r--src/mame/drivers/royalmah.c108
-rw-r--r--src/mame/drivers/rpunch.c2
-rw-r--r--src/mame/drivers/runaway.c10
-rw-r--r--src/mame/drivers/rungun.c18
-rw-r--r--src/mame/drivers/safarir.c2
-rw-r--r--src/mame/drivers/saturn.c276
-rw-r--r--src/mame/drivers/sbowling.c4
-rw-r--r--src/mame/drivers/sbrkout.c58
-rw-r--r--src/mame/drivers/scobra.c2
-rw-r--r--src/mame/drivers/scramble.c6
-rw-r--r--src/mame/drivers/scregg.c2
-rw-r--r--src/mame/drivers/sderby.c10
-rw-r--r--src/mame/drivers/seattle.c22
-rw-r--r--src/mame/drivers/segac2.c6
-rw-r--r--src/mame/drivers/segae.c8
-rw-r--r--src/mame/drivers/segag80r.c22
-rw-r--r--src/mame/drivers/segag80v.c18
-rw-r--r--src/mame/drivers/segahang.c10
-rw-r--r--src/mame/drivers/segaorun.c8
-rw-r--r--src/mame/drivers/segas16a.c62
-rw-r--r--src/mame/drivers/segas16b.c80
-rw-r--r--src/mame/drivers/segas18.c42
-rw-r--r--src/mame/drivers/segas24.c66
-rw-r--r--src/mame/drivers/segas32.c14
-rw-r--r--src/mame/drivers/segaxbd.c14
-rw-r--r--src/mame/drivers/segaybd.c4
-rw-r--r--src/mame/drivers/seibuspi.c38
-rw-r--r--src/mame/drivers/seicross.c2
-rw-r--r--src/mame/drivers/sengokmj.c14
-rw-r--r--src/mame/drivers/seta.c378
-rw-r--r--src/mame/drivers/seta2.c34
-rw-r--r--src/mame/drivers/sf.c4
-rw-r--r--src/mame/drivers/sfbonus.c4
-rw-r--r--src/mame/drivers/sfkick.c10
-rw-r--r--src/mame/drivers/shadfrce.c8
-rw-r--r--src/mame/drivers/shangha3.c10
-rw-r--r--src/mame/drivers/shangkid.c2
-rw-r--r--src/mame/drivers/shisen.c14
-rw-r--r--src/mame/drivers/shootout.c2
-rw-r--r--src/mame/drivers/shuuz.c10
-rw-r--r--src/mame/drivers/sidearms.c6
-rw-r--r--src/mame/drivers/sigmab98.c8
-rw-r--r--src/mame/drivers/simpl156.c6
-rw-r--r--src/mame/drivers/skimaxx.c6
-rw-r--r--src/mame/drivers/skullxbo.c4
-rw-r--r--src/mame/drivers/skydiver.c2
-rw-r--r--src/mame/drivers/skyfox.c2
-rw-r--r--src/mame/drivers/skykid.c14
-rw-r--r--src/mame/drivers/skyraid.c6
-rw-r--r--src/mame/drivers/slapshot.c6
-rw-r--r--src/mame/drivers/slotcarn.c4
-rw-r--r--src/mame/drivers/snesb.c6
-rw-r--r--src/mame/drivers/snk.c28
-rw-r--r--src/mame/drivers/snk68.c14
-rw-r--r--src/mame/drivers/snookr10.c2
-rw-r--r--src/mame/drivers/snowbros.c38
-rw-r--r--src/mame/drivers/spcforce.c4
-rw-r--r--src/mame/drivers/spdodgeb.c18
-rw-r--r--src/mame/drivers/speedatk.c4
-rw-r--r--src/mame/drivers/spiders.c6
-rw-r--r--src/mame/drivers/splash.c2
-rw-r--r--src/mame/drivers/splus.c20
-rw-r--r--src/mame/drivers/spoker.c10
-rw-r--r--src/mame/drivers/spool99.c44
-rw-r--r--src/mame/drivers/sprint2.c12
-rw-r--r--src/mame/drivers/sprint4.c30
-rw-r--r--src/mame/drivers/sprint8.c8
-rw-r--r--src/mame/drivers/srmp2.c4
-rw-r--r--src/mame/drivers/srmp5.c8
-rw-r--r--src/mame/drivers/srmp6.c10
-rw-r--r--src/mame/drivers/ssfindo.c10
-rw-r--r--src/mame/drivers/sshangha.c46
-rw-r--r--src/mame/drivers/ssingles.c2
-rw-r--r--src/mame/drivers/ssozumo.c2
-rw-r--r--src/mame/drivers/ssrj.c2
-rw-r--r--src/mame/drivers/sstrangr.c4
-rw-r--r--src/mame/drivers/ssv.c38
-rw-r--r--src/mame/drivers/st0016.c18
-rw-r--r--src/mame/drivers/stactics.c4
-rw-r--r--src/mame/drivers/stadhero.c8
-rw-r--r--src/mame/drivers/starfire.c16
-rw-r--r--src/mame/drivers/starshp1.c10
-rw-r--r--src/mame/drivers/statriv2.c2
-rw-r--r--src/mame/drivers/stlforce.c2
-rw-r--r--src/mame/drivers/stv.c16
-rw-r--r--src/mame/drivers/subs.c2
-rw-r--r--src/mame/drivers/subsino2.c12
-rw-r--r--src/mame/drivers/suna8.c10
-rw-r--r--src/mame/drivers/supbtime.c10
-rw-r--r--src/mame/drivers/superchs.c10
-rw-r--r--src/mame/drivers/superqix.c32
-rw-r--r--src/mame/drivers/suprgolf.c8
-rw-r--r--src/mame/drivers/suprnova.c2
-rw-r--r--src/mame/drivers/suprridr.c4
-rw-r--r--src/mame/drivers/system1.c6
-rw-r--r--src/mame/drivers/system16.c42
-rw-r--r--src/mame/drivers/tagteam.c10
-rw-r--r--src/mame/drivers/tail2nos.c2
-rw-r--r--src/mame/drivers/taito_b.c20
-rw-r--r--src/mame/drivers/taito_f2.c98
-rw-r--r--src/mame/drivers/taito_f3.c6
-rw-r--r--src/mame/drivers/taito_h.c16
-rw-r--r--src/mame/drivers/taito_l.c58
-rw-r--r--src/mame/drivers/taito_o.c4
-rw-r--r--src/mame/drivers/taito_x.c14
-rw-r--r--src/mame/drivers/taito_z.c50
-rw-r--r--src/mame/drivers/taitoair.c12
-rw-r--r--src/mame/drivers/taitogn.c12
-rw-r--r--src/mame/drivers/taitojc.c20
-rw-r--r--src/mame/drivers/taitosj.c6
-rw-r--r--src/mame/drivers/tank8.c2
-rw-r--r--src/mame/drivers/tankbatt.c6
-rw-r--r--src/mame/drivers/tapatune.c6
-rw-r--r--src/mame/drivers/tatsumi.c20
-rw-r--r--src/mame/drivers/taxidriv.c2
-rw-r--r--src/mame/drivers/tceptor.c8
-rw-r--r--src/mame/drivers/tecmo.c8
-rw-r--r--src/mame/drivers/tecmosys.c4
-rw-r--r--src/mame/drivers/tehkanwc.c12
-rw-r--r--src/mame/drivers/tempest.c10
-rw-r--r--src/mame/drivers/terracre.c2
-rw-r--r--src/mame/drivers/tetrisp2.c4
-rw-r--r--src/mame/drivers/thayers.c6
-rw-r--r--src/mame/drivers/thedeep.c6
-rw-r--r--src/mame/drivers/thepit.c16
-rw-r--r--src/mame/drivers/thief.c10
-rw-r--r--src/mame/drivers/thunderj.c4
-rw-r--r--src/mame/drivers/tiamc1.c2
-rw-r--r--src/mame/drivers/tickee.c4
-rw-r--r--src/mame/drivers/timetrv.c4
-rw-r--r--src/mame/drivers/tmaster.c6
-rw-r--r--src/mame/drivers/tmmjprd.c12
-rw-r--r--src/mame/drivers/tmnt.c22
-rw-r--r--src/mame/drivers/tmspoker.c2
-rw-r--r--src/mame/drivers/tnzs.c4
-rw-r--r--src/mame/drivers/toaplan1.c6
-rw-r--r--src/mame/drivers/toaplan2.c152
-rw-r--r--src/mame/drivers/tomcat.c6
-rw-r--r--src/mame/drivers/toobin.c4
-rw-r--r--src/mame/drivers/topspeed.c4
-rw-r--r--src/mame/drivers/toratora.c10
-rw-r--r--src/mame/drivers/tourtabl.c2
-rw-r--r--src/mame/drivers/toypop.c28
-rw-r--r--src/mame/drivers/trackfld.c8
-rw-r--r--src/mame/drivers/triplhnt.c12
-rw-r--r--src/mame/drivers/truco.c2
-rw-r--r--src/mame/drivers/tryout.c2
-rw-r--r--src/mame/drivers/tugboat.c10
-rw-r--r--src/mame/drivers/tumbleb.c36
-rw-r--r--src/mame/drivers/tumblep.c8
-rw-r--r--src/mame/drivers/tunhunt.c14
-rw-r--r--src/mame/drivers/turbo.c14
-rw-r--r--src/mame/drivers/twin16.c14
-rw-r--r--src/mame/drivers/twincobr.c6
-rw-r--r--src/mame/drivers/twinkle.c12
-rw-r--r--src/mame/drivers/tx1.c16
-rw-r--r--src/mame/drivers/uapce.c6
-rw-r--r--src/mame/drivers/ultratnk.c16
-rw-r--r--src/mame/drivers/ultrsprt.c6
-rw-r--r--src/mame/drivers/undrfire.c14
-rw-r--r--src/mame/drivers/unico.c8
-rw-r--r--src/mame/drivers/unkhorse.c6
-rw-r--r--src/mame/drivers/upscope.c2
-rw-r--r--src/mame/drivers/usgames.c2
-rw-r--r--src/mame/drivers/vamphalf.c2
-rw-r--r--src/mame/drivers/vaportra.c8
-rw-r--r--src/mame/drivers/vball.c2
-rw-r--r--src/mame/drivers/vcombat.c6
-rw-r--r--src/mame/drivers/vegaeo.c2
-rw-r--r--src/mame/drivers/vegas.c2
-rw-r--r--src/mame/drivers/vendetta.c6
-rw-r--r--src/mame/drivers/vicdual.c42
-rw-r--r--src/mame/drivers/videopin.c6
-rw-r--r--src/mame/drivers/videopkr.c8
-rw-r--r--src/mame/drivers/vindictr.c4
-rw-r--r--src/mame/drivers/viper.c4
-rw-r--r--src/mame/drivers/vmetal.c18
-rw-r--r--src/mame/drivers/voyager.c2
-rw-r--r--src/mame/drivers/vpoker.c2
-rw-r--r--src/mame/drivers/wardner.c2
-rw-r--r--src/mame/drivers/warpsped.c2
-rw-r--r--src/mame/drivers/warpwarp.c74
-rw-r--r--src/mame/drivers/wecleman.c12
-rw-r--r--src/mame/drivers/wgp.c6
-rw-r--r--src/mame/drivers/williams.c8
-rw-r--r--src/mame/drivers/wink.c4
-rw-r--r--src/mame/drivers/wiping.c2
-rw-r--r--src/mame/drivers/witch.c14
-rw-r--r--src/mame/drivers/wolfpack.c2
-rw-r--r--src/mame/drivers/wwfwfest.c6
-rw-r--r--src/mame/drivers/xexex.c4
-rw-r--r--src/mame/drivers/xmen.c2
-rw-r--r--src/mame/drivers/xtheball.c4
-rw-r--r--src/mame/drivers/xxmissio.c2
-rw-r--r--src/mame/drivers/xybots.c4
-rw-r--r--src/mame/drivers/xyonix.c16
-rw-r--r--src/mame/drivers/yunsung8.c4
-rw-r--r--src/mame/drivers/zac2650.c4
-rw-r--r--src/mame/drivers/zaccaria.c4
-rw-r--r--src/mame/drivers/zaxxon.c2
-rw-r--r--src/mame/drivers/zn.c10
-rw-r--r--src/mame/drivers/zr107.c14
-rw-r--r--src/mame/includes/galpnipt.h32
-rw-r--r--src/mame/includes/iremipt.h28
-rw-r--r--src/mame/includes/lordgun.h2
-rw-r--r--src/mame/includes/toaplipt.h56
-rw-r--r--src/mame/machine/acitya.c2
-rw-r--r--src/mame/machine/ajax.c8
-rw-r--r--src/mame/machine/amiga.c12
-rw-r--r--src/mame/machine/arkanoid.c4
-rw-r--r--src/mame/machine/asteroid.c14
-rw-r--r--src/mame/machine/atari.c16
-rw-r--r--src/mame/machine/atarifb.c30
-rw-r--r--src/mame/machine/balsente.c16
-rw-r--r--src/mame/machine/beezer.c8
-rw-r--r--src/mame/machine/bonzeadv.c8
-rw-r--r--src/mame/machine/bsktball.c10
-rw-r--r--src/mame/machine/bublbobl.c6
-rw-r--r--src/mame/machine/carpolo.c8
-rw-r--r--src/mame/machine/cchip.c6
-rw-r--r--src/mame/machine/cdislave.c6
-rw-r--r--src/mame/machine/dc-ctrl.c32
-rw-r--r--src/mame/machine/dec0.c20
-rw-r--r--src/mame/machine/decocass.c10
-rw-r--r--src/mame/machine/decoprot.c78
-rw-r--r--src/mame/machine/gaelco2.c4
-rw-r--r--src/mame/machine/galaxold.c4
-rw-r--r--src/mame/machine/gaplus.c2
-rw-r--r--src/mame/machine/harddriv.c14
-rw-r--r--src/mame/machine/irobot.c4
-rw-r--r--src/mame/machine/jvs13551.c8
-rw-r--r--src/mame/machine/kaneko16.c10
-rw-r--r--src/mame/machine/leland.c66
-rw-r--r--src/mame/machine/lsasquad.c4
-rw-r--r--src/mame/machine/mcr68.c4
-rw-r--r--src/mame/machine/megadriv.c34
-rw-r--r--src/mame/machine/mexico86.c8
-rw-r--r--src/mame/machine/mhavoc.c2
-rw-r--r--src/mame/machine/micro3d.c12
-rw-r--r--src/mame/machine/midtunit.c2
-rw-r--r--src/mame/machine/midwayic.c8
-rw-r--r--src/mame/machine/midwunit.c4
-rw-r--r--src/mame/machine/midxunit.c6
-rw-r--r--src/mame/machine/midyunit.c12
-rw-r--r--src/mame/machine/mie.c4
-rw-r--r--src/mame/machine/n64.c6
-rw-r--r--src/mame/machine/namcos1.c30
-rw-r--r--src/mame/machine/namcos2.c38
-rw-r--r--src/mame/machine/nb1413m3.c120
-rw-r--r--src/mame/machine/nitedrvr.c12
-rw-r--r--src/mame/machine/opwolf.c4
-rw-r--r--src/mame/machine/pcecommn.c2
-rw-r--r--src/mame/machine/pckeybrd.c20
-rw-r--r--src/mame/machine/pgmprot.c6
-rw-r--r--src/mame/machine/pgmprot1.c6
-rw-r--r--src/mame/machine/pgmprot2.c18
-rw-r--r--src/mame/machine/pgmprot4.c4
-rw-r--r--src/mame/machine/pgmprot6.c2
-rw-r--r--src/mame/machine/playch10.c12
-rw-r--r--src/mame/machine/qix.c8
-rw-r--r--src/mame/machine/rainbow.c8
-rw-r--r--src/mame/machine/scramble.c2
-rw-r--r--src/mame/machine/segamsys.c8
-rw-r--r--src/mame/machine/seicop.c32
-rw-r--r--src/mame/machine/simpsons.c2
-rw-r--r--src/mame/machine/slikshot.c4
-rw-r--r--src/mame/machine/smpc.c54
-rw-r--r--src/mame/machine/snes.c12
-rw-r--r--src/mame/machine/starwars.c4
-rw-r--r--src/mame/machine/stfight.c4
-rw-r--r--src/mame/machine/subs.c12
-rw-r--r--src/mame/machine/tait8741.c22
-rw-r--r--src/mame/machine/taitosj.c4
-rw-r--r--src/mame/machine/tatsumi.c8
-rw-r--r--src/mame/machine/tnzs.c32
-rw-r--r--src/mame/machine/toaplan1.c8
-rw-r--r--src/mame/machine/vectrex.c8
-rw-r--r--src/mame/machine/vertigo.c6
-rw-r--r--src/mame/machine/volfied.c8
-rw-r--r--src/mame/machine/vsnes.c42
-rw-r--r--src/mame/machine/williams.c10
-rw-r--r--src/mame/machine/xevious.c8
-rw-r--r--src/mame/video/aeroboto.c2
-rw-r--r--src/mame/video/amiga.c2
-rw-r--r--src/mame/video/argus.c2
-rw-r--r--src/mame/video/artmagic.c2
-rw-r--r--src/mame/video/astrocde.c24
-rw-r--r--src/mame/video/atari.c4
-rw-r--r--src/mame/video/atarisy1.c2
-rw-r--r--src/mame/video/balsente.c6
-rw-r--r--src/mame/video/bking.c4
-rw-r--r--src/mame/video/blockade.c2
-rw-r--r--src/mame/video/btime.c6
-rw-r--r--src/mame/video/bwing.c2
-rw-r--r--src/mame/video/canyon.c2
-rw-r--r--src/mame/video/cave.c4
-rw-r--r--src/mame/video/centiped.c2
-rw-r--r--src/mame/video/changela.c10
-rw-r--r--src/mame/video/cinemat.c2
-rw-r--r--src/mame/video/cischeat.c42
-rw-r--r--src/mame/video/cosmic.c2
-rw-r--r--src/mame/video/cps1.c4
-rw-r--r--src/mame/video/dc.c2
-rw-r--r--src/mame/video/dcheese.c6
-rw-r--r--src/mame/video/deco_mlc.c2
-rw-r--r--src/mame/video/decocass.c2
-rw-r--r--src/mame/video/dkong.c12
-rw-r--r--src/mame/video/dooyong.c30
-rw-r--r--src/mame/video/dynax.c4
-rw-r--r--src/mame/video/esripsys.c2
-rw-r--r--src/mame/video/exerion.c2
-rw-r--r--src/mame/video/exidy.c2
-rw-r--r--src/mame/video/exidy440.c4
-rw-r--r--src/mame/video/f1gp.c4
-rw-r--r--src/mame/video/fgoal.c2
-rw-r--r--src/mame/video/gomoku.c4
-rw-r--r--src/mame/video/hyprduel.c2
-rw-r--r--src/mame/video/itech32.c2
-rw-r--r--src/mame/video/itech8.c4
-rw-r--r--src/mame/video/jaguar.c6
-rw-r--r--src/mame/video/kangaroo.c2
-rw-r--r--src/mame/video/lazercmd.c4
-rw-r--r--src/mame/video/lethalj.c6
-rw-r--r--src/mame/video/lordgun.c12
-rw-r--r--src/mame/video/lwings.c2
-rw-r--r--src/mame/video/m52.c2
-rw-r--r--src/mame/video/m57.c2
-rw-r--r--src/mame/video/m58.c2
-rw-r--r--src/mame/video/m62.c2
-rw-r--r--src/mame/video/m72.c4
-rw-r--r--src/mame/video/m92.c4
-rw-r--r--src/mame/video/madalien.c2
-rw-r--r--src/mame/video/mario.c2
-rw-r--r--src/mame/video/mcatadv.c2
-rw-r--r--src/mame/video/mcd212.c2
-rw-r--r--src/mame/video/metro.c2
-rw-r--r--src/mame/video/model2.c2
-rw-r--r--src/mame/video/momoko.c2
-rw-r--r--src/mame/video/mystston.c2
-rw-r--r--src/mame/video/n8080.c4
-rw-r--r--src/mame/video/namcos22.c4
-rw-r--r--src/mame/video/naughtyb.c4
-rw-r--r--src/mame/video/neogeo.c2
-rw-r--r--src/mame/video/nmk16.c4
-rw-r--r--src/mame/video/oneshot.c8
-rw-r--r--src/mame/video/opwolf.c4
-rw-r--r--src/mame/video/orbit.c2
-rw-r--r--src/mame/video/pgm.c2
-rw-r--r--src/mame/video/phoenix.c10
-rw-r--r--src/mame/video/policetr.c10
-rw-r--r--src/mame/video/prehisle.c10
-rw-r--r--src/mame/video/psikyo.c4
-rw-r--r--src/mame/video/psychic5.c10
-rw-r--r--src/mame/video/route16.c2
-rw-r--r--src/mame/video/shisen.c2
-rw-r--r--src/mame/video/snes.c10
-rw-r--r--src/mame/video/system1.c2
-rw-r--r--src/mame/video/thepit.c4
-rw-r--r--src/mame/video/tmnt.c2
-rw-r--r--src/mame/video/travrusa.c2
-rw-r--r--src/mame/video/turbo.c4
-rw-r--r--src/mame/video/tx1.c22
-rw-r--r--src/mame/video/undrfire.c4
-rw-r--r--src/mame/video/vectrex.c6
-rw-r--r--src/mame/video/vertigo.c2
-rw-r--r--src/mame/video/wecleman.c2
-rw-r--r--src/mame/video/zac2650.c2
-rw-r--r--src/osd/sdl/input.c58
-rw-r--r--src/osd/windows/debugwin.c2
-rw-r--r--src/osd/windows/input.c23
881 files changed, 10851 insertions, 10975 deletions
diff --git a/makefile b/makefile
index 573ec648cac..281148300e6 100644
--- a/makefile
+++ b/makefile
@@ -474,19 +474,15 @@ endif
# add the optimization flag
CCOMFLAGS += -O$(OPTIMIZE)
-# if we are optimizing, include optimization options
-# and make all errors into warnings
-ifneq ($(OPTIMIZE),0)
-ifneq ($(TARGETOS),os2)
+# add the error warning flag
ifndef NOWERROR
-CCOMFLAGS += -Werror -fno-strict-aliasing $(ARCHOPTS)
-else
-CCOMFLAGS += -fno-strict-aliasing $(ARCHOPTS)
+CCOMFLAGS += -Werror
endif
-else
+
+# if we are optimizing, include optimization options
+ifneq ($(OPTIMIZE),0)
CCOMFLAGS += -fno-strict-aliasing $(ARCHOPTS)
endif
-endif
# add a basic set of warnings
CCOMFLAGS += \
diff --git a/src/emu/crsshair.c b/src/emu/crsshair.c
index 693d620cf19..cd4a86d427b 100644
--- a/src/emu/crsshair.c
+++ b/src/emu/crsshair.c
@@ -221,11 +221,11 @@ void crosshair_init(running_machine &machine)
global.auto_time = CROSSHAIR_VISIBILITY_AUTOTIME_DEFAULT;
/* determine who needs crosshairs */
- for (input_port_config *port = machine.ioport().first_port(); port != NULL; port = port->next())
- for (input_field_config *field = port->fieldlist().first(); field != NULL; field = field->next())
- if (field->crossaxis != CROSSHAIR_AXIS_NONE)
+ for (ioport_port *port = machine.ioport().first_port(); port != NULL; port = port->next())
+ for (ioport_field *field = port->first_field(); field != NULL; field = field->next())
+ if (field->crosshair_axis() != CROSSHAIR_AXIS_NONE)
{
- int player = field->player;
+ int player = field->player();
assert(player < MAX_PLAYERS);
@@ -347,7 +347,7 @@ static void animate(running_machine &machine, screen_device &device, bool vblank
{
/* read all the lightgun values */
if (global.used[player])
- input_port_get_crosshair_position(device.machine(), player, &global.x[player], &global.y[player]);
+ device.machine().ioport().crosshair_position(player, global.x[player], global.y[player]);
/* auto visibility */
if (global.mode[player] == CROSSHAIR_VISIBILITY_AUTO)
diff --git a/src/emu/devcb.c b/src/emu/devcb.c
index bb338d602ae..83ddadf6b20 100644
--- a/src/emu/devcb.c
+++ b/src/emu/devcb.c
@@ -63,7 +63,7 @@ UINT8 devcb_resolved_write16::s_null;
class devcb_resolver
{
public:
- static const input_port_config *resolve_port(const char *tag, device_t &current);
+ static ioport_port *resolve_port(const char *tag, device_t &current);
static device_t *resolve_device(int index, const char *tag, device_t &current);
static device_execute_interface *resolve_execute_interface(const char *tag, device_t &current);
static address_space *resolve_space(int index, const char *tag, device_t &current);
@@ -80,10 +80,10 @@ public:
// based on the provided tag
//-------------------------------------------------
-const input_port_config *devcb_resolver::resolve_port(const char *tag, device_t &current)
+ioport_port *devcb_resolver::resolve_port(const char *tag, device_t &current)
{
astring fullname;
- const input_port_config *result = current.ioport(current.siblingtag(fullname, tag));
+ ioport_port *result = current.ioport(current.siblingtag(fullname, tag));
if (result == NULL)
throw emu_fatalerror("Unable to find input port '%s' (requested by %s '%s')", fullname.cstr(), current.name(), current.tag());
return result;
@@ -221,7 +221,7 @@ void devcb_resolved_read_line::resolve(const devcb_read_line &desc, device_t &de
int devcb_resolved_read_line::from_port()
{
- return (input_port_read_direct(m_object.port) & 1) ? ASSERT_LINE : CLEAR_LINE;
+ return (m_object.port->read() & 1) ? ASSERT_LINE : CLEAR_LINE;
}
@@ -325,7 +325,7 @@ void devcb_resolved_write_line::to_null(int state)
void devcb_resolved_write_line::to_port(int state)
{
- input_port_write_direct(m_object.port, state, 0xffffffff);
+ m_object.port->write(state, 0xffffffff);
}
@@ -419,7 +419,7 @@ void devcb_resolved_read8::resolve(const devcb_read8 &desc, device_t &device)
UINT8 devcb_resolved_read8::from_port(offs_t offset)
{
- return input_port_read_direct(m_object.port);
+ return m_object.port->read();
}
@@ -522,7 +522,7 @@ void devcb_resolved_write8::to_null(offs_t offset, UINT8 data)
void devcb_resolved_write8::to_port(offs_t offset, UINT8 data)
{
- input_port_write_direct(m_object.port, data, 0xff);
+ m_object.port->write(data, 0xff);
}
@@ -616,7 +616,7 @@ void devcb_resolved_read16::resolve(const devcb_read16 &desc, device_t &device)
UINT16 devcb_resolved_read16::from_port(offs_t offset, UINT16 mask)
{
- return input_port_read_direct(m_object.port);
+ return m_object.port->read();
}
@@ -719,7 +719,7 @@ void devcb_resolved_write16::to_null(offs_t offset, UINT16 data, UINT16 mask)
void devcb_resolved_write16::to_port(offs_t offset, UINT16 data, UINT16 mask)
{
- input_port_write_direct(m_object.port, data, mask);
+ m_object.port->write(data, mask);
}
diff --git a/src/emu/devcb.h b/src/emu/devcb.h
index 1dcb8e49a20..2f323b41311 100644
--- a/src/emu/devcb.h
+++ b/src/emu/devcb.h
@@ -203,7 +203,7 @@ void devcb_stub16(device_t *device, offs_t offset, UINT16 data, UINT16 mask)
// resolving a devcb may produce one of the following object types
union devcb_resolved_objects
{
- const input_port_config * port;
+ ioport_port * port;
address_space * space;
device_t * device;
device_execute_interface * execute;
diff --git a/src/emu/device.c b/src/emu/device.c
index 350a80d305c..2ecf2a6839f 100644
--- a/src/emu/device.c
+++ b/src/emu/device.c
@@ -239,7 +239,7 @@ memory_bank *device_t::membank(const char *_tag) const
// object for a given port name
//-------------------------------------------------
-input_port_config *device_t::ioport(const char *tag) const
+ioport_port *device_t::ioport(const char *tag) const
{
// safety first
if (this == NULL)
diff --git a/src/emu/device.h b/src/emu/device.h
index 2ca4343b989..a1a4cafec77 100644
--- a/src/emu/device.h
+++ b/src/emu/device.h
@@ -95,7 +95,7 @@ class validity_checker;
struct rom_entry;
class machine_config;
class emu_timer;
-typedef struct _input_device_default input_device_default;
+struct input_device_default;
@@ -188,7 +188,7 @@ public:
memory_region *memregion(const char *tag) const;
memory_share *memshare(const char *tag) const;
memory_bank *membank(const char *tag) const;
- input_port_config *ioport(const char *tag) const;
+ ioport_port *ioport(const char *tag) const;
device_t *subdevice(const char *tag) const;
device_t *siblingdevice(const char *tag) const;
template<class _DeviceClass> inline _DeviceClass *subdevice(const char *tag) const { return downcast<_DeviceClass *>(subdevice(tag)); }
@@ -506,12 +506,12 @@ public:
// device finder template
template<bool _Required>
-class device_t::ioport_finder : public device_t::object_finder_base<input_port_config>
+class device_t::ioport_finder : public device_t::object_finder_base<ioport_port>
{
public:
// construction/destruction
ioport_finder(device_t &base, const char *tag)
- : object_finder_base<input_port_config>(base, tag) { }
+ : object_finder_base<ioport_port>(base, tag) { }
// finder
virtual bool findit()
@@ -927,36 +927,6 @@ private:
};
-// ======================> device_delegate
-
-// device_delegate is a delegate that wraps with a device tag and can be easily
-// late bound without replicating logic everywhere
-template<typename _Signature>
-class device_delegate : public delegate<_Signature>
-{
- typedef delegate<_Signature> basetype;
-
-public:
- // provide same set of constructors as the base class, with additional device name
- // parameter
- device_delegate() : basetype(), m_device_name(NULL) { }
- device_delegate(const basetype &src) : basetype(src), m_device_name(src.m_device_name) { }
- device_delegate(const basetype &src, delegate_late_bind &object) : basetype(src, object), m_device_name(src.m_device_name) { }
- template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::member_func_type funcptr, const char *name, const char *devname) : basetype(funcptr, name, (_FunctionClass *)0), m_device_name(devname) { }
- template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::member_func_type funcptr, const char *name, const char *devname, _FunctionClass *object) : basetype(funcptr, name, (_FunctionClass *)0), m_device_name(devname) { }
- device_delegate(typename basetype::template traits<device_t>::static_func_type funcptr, const char *name) : basetype(funcptr, name, (device_t *)0), m_device_name(NULL) { }
- device_delegate(typename basetype::template traits<device_t>::static_ref_func_type funcptr, const char *name) : basetype(funcptr, name, (device_t *)0), m_device_name(NULL) { }
- device_delegate &operator=(const basetype &src) { *static_cast<basetype *>(this) = src; m_device_name = src.m_device_name; return *this; }
-
- // perform the binding
- void bind_relative_to(device_t &search_root);
-
-private:
- // internal state
- const char *m_device_name;
-};
-
-
//**************************************************************************
// INLINE FUNCTIONS
diff --git a/src/emu/emu.h b/src/emu/emu.h
index e39935f2e9b..a0e75095db4 100644
--- a/src/emu/emu.h
+++ b/src/emu/emu.h
@@ -81,6 +81,35 @@
class machine_config;
typedef device_t * (*machine_config_constructor)(machine_config &config, device_t *owner);
+// device_delegate is a delegate that wraps with a device tag and can be easily
+// late bound without replicating logic everywhere
+template<typename _Signature>
+class device_delegate : public delegate<_Signature>
+{
+ typedef delegate<_Signature> basetype;
+
+public:
+ // provide same set of constructors as the base class, with additional device name
+ // parameter
+ device_delegate() : basetype(), m_device_name(NULL) { }
+ device_delegate(const basetype &src) : basetype(src), m_device_name(src.m_device_name) { }
+ device_delegate(const basetype &src, delegate_late_bind &object) : basetype(src, object), m_device_name(src.m_device_name) { }
+ template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::member_func_type funcptr, const char *name, const char *devname) : basetype(funcptr, name, (_FunctionClass *)0), m_device_name(devname) { }
+ template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::member_func_type funcptr, const char *name, const char *devname, _FunctionClass *object) : basetype(funcptr, name, (_FunctionClass *)0), m_device_name(devname) { }
+ template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::static_func_type funcptr, const char *name, const char *devname, _FunctionClass *object) : basetype(funcptr, name, (_FunctionClass *)0), m_device_name(devname) { }
+ template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::static_ref_func_type funcptr, const char *name, const char *devname, _FunctionClass *object) : basetype(funcptr, name, (_FunctionClass *)0), m_device_name(devname) { }
+ device_delegate(typename basetype::template traits<device_t>::static_func_type funcptr, const char *name) : basetype(funcptr, name, (device_t *)0), m_device_name(NULL) { }
+ device_delegate(typename basetype::template traits<device_t>::static_ref_func_type funcptr, const char *name) : basetype(funcptr, name, (device_t *)0), m_device_name(NULL) { }
+ device_delegate &operator=(const basetype &src) { *static_cast<basetype *>(this) = src; m_device_name = src.m_device_name; return *this; }
+
+ // perform the binding
+ void bind_relative_to(device_t &search_root);
+
+private:
+ // internal state
+ const char *m_device_name;
+};
+
// I/O
#include "input.h"
#include "ioport.h"
diff --git a/src/emu/info.c b/src/emu/info.c
index e29fb7108d4..af3588818b4 100644
--- a/src/emu/info.c
+++ b/src/emu/info.c
@@ -267,7 +267,7 @@ void info_xml_creator::output_one()
astring errors;
device_iterator iter(config.root_device());
for (device_t *device = iter.first(); device != NULL; device = iter.next())
- input_port_list_init(*device, portlist, errors);
+ portlist.append(*device, errors);
// print the header and the game name
fprintf(m_output, "\t<%s",emulator_info::get_xml_top());
@@ -352,11 +352,11 @@ void info_xml_creator::output_one_device(device_t &device, const char *devtag)
astring errors;
device_iterator iptiter(device);
for (device_t *dev = iptiter.first(); dev != NULL; dev = iptiter.next())
- input_port_list_init(*dev, portlist, errors);
+ portlist.append(*dev, errors);
// check if the device adds player inputs (other than dsw and configs) to the system
- for (input_port_config *port = portlist.first(); port != NULL; port = port->next())
- for (input_field_config *field = port->fieldlist().first(); field != NULL; field = field->next())
- if (field->type >= IPT_START1 && field->type < __ipt_ui_start)
+ for (ioport_port *port = portlist.first(); port != NULL; port = port->next())
+ for (ioport_field *field = port->first_field(); field != NULL; field = field->next())
+ if (field->type() >= IPT_START1 && field->type() < IPT_UI_FIRST)
{
has_input = TRUE;
break;
@@ -830,33 +830,33 @@ void info_xml_creator::output_input(const ioport_list &portlist)
bool gambling = false;
// iterate over the ports
- for (input_port_config *port = portlist.first(); port != NULL; port = port->next())
- for (input_field_config *field = port->fieldlist().first(); field != NULL; field = field->next())
+ for (ioport_port *port = portlist.first(); port != NULL; port = port->next())
+ for (ioport_field *field = port->first_field(); field != NULL; field = field->next())
{
int analogtype = -1;
// track the highest player number
- if (nplayer < field->player + 1)
- nplayer = field->player + 1;
+ if (nplayer < field->player() + 1)
+ nplayer = field->player() + 1;
// switch off of the type
- switch (field->type)
+ switch (field->type())
{
// map which joystick directions are present
- case IPT_JOYSTICK_UP: joytype[0] |= DIR_UP | ((field->way == 4) ? DIR_4WAY : 0); break;
- case IPT_JOYSTICK_DOWN: joytype[0] |= DIR_DOWN | ((field->way == 4) ? DIR_4WAY : 0); break;
- case IPT_JOYSTICK_LEFT: joytype[0] |= DIR_LEFT | ((field->way == 4) ? DIR_4WAY : 0); break;
- case IPT_JOYSTICK_RIGHT: joytype[0] |= DIR_RIGHT | ((field->way == 4) ? DIR_4WAY : 0); break;
+ case IPT_JOYSTICK_UP: joytype[0] |= DIR_UP | ((field->way() == 4) ? DIR_4WAY : 0); break;
+ case IPT_JOYSTICK_DOWN: joytype[0] |= DIR_DOWN | ((field->way() == 4) ? DIR_4WAY : 0); break;
+ case IPT_JOYSTICK_LEFT: joytype[0] |= DIR_LEFT | ((field->way() == 4) ? DIR_4WAY : 0); break;
+ case IPT_JOYSTICK_RIGHT: joytype[0] |= DIR_RIGHT | ((field->way() == 4) ? DIR_4WAY : 0); break;
- case IPT_JOYSTICKLEFT_UP: joytype[1] |= DIR_UP | ((field->way == 4) ? DIR_4WAY : 0); break;
- case IPT_JOYSTICKLEFT_DOWN: joytype[1] |= DIR_DOWN | ((field->way == 4) ? DIR_4WAY : 0); break;
- case IPT_JOYSTICKLEFT_LEFT: joytype[1] |= DIR_LEFT | ((field->way == 4) ? DIR_4WAY : 0); break;
- case IPT_JOYSTICKLEFT_RIGHT: joytype[1] |= DIR_RIGHT | ((field->way == 4) ? DIR_4WAY : 0); break;
+ case IPT_JOYSTICKLEFT_UP: joytype[1] |= DIR_UP | ((field->way() == 4) ? DIR_4WAY : 0); break;
+ case IPT_JOYSTICKLEFT_DOWN: joytype[1] |= DIR_DOWN | ((field->way() == 4) ? DIR_4WAY : 0); break;
+ case IPT_JOYSTICKLEFT_LEFT: joytype[1] |= DIR_LEFT | ((field->way() == 4) ? DIR_4WAY : 0); break;
+ case IPT_JOYSTICKLEFT_RIGHT: joytype[1] |= DIR_RIGHT | ((field->way() == 4) ? DIR_4WAY : 0); break;
- case IPT_JOYSTICKRIGHT_UP: joytype[2] |= DIR_UP | ((field->way == 4) ? DIR_4WAY : 0); break;
- case IPT_JOYSTICKRIGHT_DOWN: joytype[2] |= DIR_DOWN | ((field->way == 4) ? DIR_4WAY : 0); break;
- case IPT_JOYSTICKRIGHT_LEFT: joytype[2] |= DIR_LEFT | ((field->way == 4) ? DIR_4WAY : 0); break;
- case IPT_JOYSTICKRIGHT_RIGHT: joytype[2] |= DIR_RIGHT | ((field->way == 4) ? DIR_4WAY : 0); break;
+ case IPT_JOYSTICKRIGHT_UP: joytype[2] |= DIR_UP | ((field->way() == 4) ? DIR_4WAY : 0); break;
+ case IPT_JOYSTICKRIGHT_DOWN: joytype[2] |= DIR_DOWN | ((field->way() == 4) ? DIR_4WAY : 0); break;
+ case IPT_JOYSTICKRIGHT_LEFT: joytype[2] |= DIR_LEFT | ((field->way() == 4) ? DIR_4WAY : 0); break;
+ case IPT_JOYSTICKRIGHT_RIGHT: joytype[2] |= DIR_RIGHT | ((field->way() == 4) ? DIR_4WAY : 0); break;
// mark as an analog input, and get analog stats after switch
case IPT_AD_STICK_X:
@@ -918,7 +918,7 @@ void info_xml_creator::output_input(const ioport_list &portlist)
case IPT_BUTTON14:
case IPT_BUTTON15:
case IPT_BUTTON16:
- nbutton = MAX(nbutton, field->type - IPT_BUTTON1 + 1);
+ nbutton = MAX(nbutton, field->type() - IPT_BUTTON1 + 1);
break;
// track maximum coin index
@@ -930,7 +930,7 @@ void info_xml_creator::output_input(const ioport_list &portlist)
case IPT_COIN6:
case IPT_COIN7:
case IPT_COIN8:
- ncoin = MAX(ncoin, field->type - IPT_COIN1 + 1);
+ ncoin = MAX(ncoin, field->type() - IPT_COIN1 + 1);
break;
// track presence of these guys
@@ -952,11 +952,11 @@ void info_xml_creator::output_input(const ioport_list &portlist)
break;
default:
- if (field->type >= __ipt_mahjong_start && field->type <= __ipt_mahjong_end)
+ if (field->type() > IPT_MAHJONG_FIRST && field->type() < IPT_MAHJONG_LAST)
mahjong = true;
- else if (field->type >= __ipt_hanafuda_start && field->type <= __ipt_hanafuda_end)
+ else if (field->type() > IPT_HANAFUDA_FIRST && field->type() < IPT_HANAFUDA_LAST)
hanafuda = true;
- else if (field->type >= __ipt_gambling_start && field->type <= __ipt_gambling_end)
+ else if (field->type() > IPT_GAMBLING_FIRST && field->type() < IPT_GAMBLING_LAST)
gambling = true;
break;
}
@@ -964,15 +964,15 @@ void info_xml_creator::output_input(const ioport_list &portlist)
// get the analog stats
if (analogtype != -1)
{
- if (field->min != 0)
- control_info[analogtype].min = field->min;
- if (field->max != 0)
- control_info[analogtype].max = field->max;
- if (field->sensitivity != 0)
- control_info[analogtype].sensitivity = field->sensitivity;
- if (field->delta != 0)
- control_info[analogtype].keydelta = field->delta;
- if ((field->flags & ANALOG_FLAG_REVERSE) != 0)
+ if (field->minval() != 0)
+ control_info[analogtype].min = field->minval();
+ if (field->maxval() != 0)
+ control_info[analogtype].max = field->maxval();
+ if (field->sensitivity() != 0)
+ control_info[analogtype].sensitivity = field->sensitivity();
+ if (field->delta() != 0)
+ control_info[analogtype].keydelta = field->delta();
+ if (field->analog_reverse() != 0)
control_info[analogtype].reverse = true;
}
}
@@ -1080,25 +1080,25 @@ void info_xml_creator::output_input(const ioport_list &portlist)
void info_xml_creator::output_switches(const ioport_list &portlist, const char *root_tag, int type, const char *outertag, const char *innertag)
{
// iterate looking for DIP switches
- for (input_port_config *port = portlist.first(); port != NULL; port = port->next())
- for (input_field_config *field = port->fieldlist().first(); field != NULL; field = field->next())
- if (field->type == type)
+ for (ioport_port *port = portlist.first(); port != NULL; port = port->next())
+ for (ioport_field *field = port->first_field(); field != NULL; field = field->next())
+ if (field->type() == type)
{
- astring newtag(field->port().tag()), oldtag(":");
+ astring newtag(port->tag()), oldtag(":");
newtag.substr(newtag.find(oldtag.cat(root_tag)) + oldtag.len());
// output the switch name information
- fprintf(m_output, "\t\t<%s name=\"%s\"", outertag, xml_normalize_string(input_field_name(field)));
+ fprintf(m_output, "\t\t<%s name=\"%s\"", outertag, xml_normalize_string(field->name()));
fprintf(m_output, " tag=\"%s\"", xml_normalize_string(newtag));
- fprintf(m_output, " mask=\"%u\"", field->mask);
+ fprintf(m_output, " mask=\"%u\"", field->mask());
fprintf(m_output, ">\n");
// loop over settings
- for (input_setting_config *setting = field->settinglist().first(); setting != NULL; setting = setting->next())
+ for (ioport_setting *setting = field->first_setting(); setting != NULL; setting = setting->next())
{
- fprintf(m_output, "\t\t\t<%s name=\"%s\"", innertag, xml_normalize_string(setting->name));
- fprintf(m_output, " value=\"%u\"", setting->value);
- if (setting->value == field->defvalue)
+ fprintf(m_output, "\t\t\t<%s name=\"%s\"", innertag, xml_normalize_string(setting->name()));
+ fprintf(m_output, " value=\"%u\"", setting->value());
+ if (setting->value() == field->defvalue())
fprintf(m_output, " default=\"yes\"");
fprintf(m_output, "/>\n");
}
@@ -1117,10 +1117,10 @@ void info_xml_creator::output_switches(const ioport_list &portlist, const char *
void info_xml_creator::output_adjusters(const ioport_list &portlist)
{
// iterate looking for Adjusters
- for (input_port_config *port = portlist.first(); port != NULL; port = port->next())
- for (input_field_config *field = port->fieldlist().first(); field != NULL; field = field->next())
- if (field->type == IPT_ADJUSTER)
- fprintf(m_output, "\t\t<adjuster name=\"%s\" default=\"%d\"/>\n", xml_normalize_string(input_field_name(field)), field->defvalue);
+ for (ioport_port *port = portlist.first(); port != NULL; port = port->next())
+ for (ioport_field *field = port->first_field(); field != NULL; field = field->next())
+ if (field->type() == IPT_ADJUSTER)
+ fprintf(m_output, "\t\t<adjuster name=\"%s\" default=\"%d\"/>\n", xml_normalize_string(field->name()), field->defvalue());
}
diff --git a/src/emu/ioport.c b/src/emu/ioport.c
index 081b1a7d6a6..2341aa9a51c 100644
--- a/src/emu/ioport.c
+++ b/src/emu/ioport.c
@@ -4,8 +4,36 @@
Input/output port handling.
- Copyright Nicola Salmoria and the MAME Team.
- Visit http://mamedev.org for licensing and usage restrictions.
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
****************************************************************************
@@ -103,459 +131,527 @@
#include <ctype.h>
#include <time.h>
-/* temporary: set this to 1 to enable the originally defined behavior that
- a field specified via PORT_MODIFY which intersects a previously-defined
- field completely wipes out the previous definition */
+// temporary: set this to 1 to enable the originally defined behavior that
+// a field specified via PORT_MODIFY which intersects a previously-defined
+// field completely wipes out the previous definition
#define INPUT_PORT_OVERRIDE_FULLY_NUKES_PREVIOUS 1
-/***************************************************************************
- CONSTANTS
-***************************************************************************/
-
-/* these constants must match the order of the joystick directions in the IPT definition */
-#define JOYDIR_UP 0
-#define JOYDIR_DOWN 1
-#define JOYDIR_LEFT 2
-#define JOYDIR_RIGHT 3
+//**************************************************************************
+// DEBUGGING
+//**************************************************************************
+
+#define LOG_NATURAL_KEYBOARD 0
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+const int SPACE_COUNT = 3;
+const int KEY_BUFFER_SIZE = 4096;
+const unicode_char INVALID_CHAR = '?';
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// live analog field information
+class analog_field
+{
+ friend class simple_list<analog_field>;
+ friend class ioport_manager;
+ friend void ioport_field::set_user_settings(const ioport_field::user_settings &settings);
+
+public:
+ // construction/destruction
+ analog_field(ioport_field &field);
+
+ // getters
+ analog_field *next() const { return m_next; }
+ ioport_manager &manager() const { return m_field.manager(); }
+ ioport_field &field() const { return m_field; }
+ INT32 sensitivity() const { return m_sensitivity; }
+ bool reverse() const { return m_reverse; }
+ INT32 delta() const { return m_delta; }
+ INT32 centerdelta() const { return m_centerdelta; }
+
+ // helpers
+ ioport_value apply_min_max(ioport_value value) const;
+ ioport_value apply_settings(ioport_value value) const;
+ ioport_value apply_sensitivity(ioport_value value) const;
+ ioport_value apply_inverse_sensitivity(ioport_value value) const;
+
+ // readers
+ void read(ioport_value &value);
+ float crosshair_read();
+ void frame_update(running_machine &machine);
+
+private:
+ // internal state
+ analog_field * m_next; // link to the next analog state for this port
+ ioport_field & m_field; // pointer to the input field referenced
+
+ // adjusted values (right-justified and tweaked)
+ UINT8 m_shift; // shift to align final value in the port
+ INT32 m_adjdefvalue; // adjusted default value from the config
+ INT32 m_adjmin; // adjusted minimum value from the config
+ INT32 m_adjmax; // adjusted maximum value from the config
+
+ // live values of configurable parameters
+ INT32 m_sensitivity; // current live sensitivity (100=normal)
+ bool m_reverse; // current live reverse flag
+ INT32 m_delta; // current live delta to apply each frame a digital inc/dec key is pressed
+ INT32 m_centerdelta; // current live delta to apply each frame no digital inputs are pressed
+
+ // live analog value tracking
+ INT32 m_accum; // accumulated value (including relative adjustments)
+ INT32 m_previous; // previous adjusted value
+ INT32 m_previousanalog; // previous analog value
+
+ // parameters for modifying live values
+ INT32 m_minimum; // minimum adjusted value
+ INT32 m_maximum; // maximum adjusted value
+ INT32 m_center; // center adjusted value for autocentering
+ INT32 m_reverse_val; // value where we subtract from to reverse directions
+
+ // scaling factors
+ INT64 m_scalepos; // scale factor to apply to positive adjusted values
+ INT64 m_scaleneg; // scale factor to apply to negative adjusted values
+ INT64 m_keyscalepos; // scale factor to apply to the key delta field when pos
+ INT64 m_keyscaleneg; // scale factor to apply to the key delta field when neg
+ INT64 m_positionalscale; // scale factor to divide a joystick into positions
+
+ // misc flags
+ bool m_absolute; // is this an absolute or relative input?
+ bool m_wraps; // does the control wrap around?
+ bool m_autocenter; // autocenter this input?
+ bool m_single_scale; // scale joystick differently if default is between min/max
+ bool m_interpolate; // should we do linear interpolation for mid-frame reads?
+ bool m_lastdigital; // was the last modification caused by a digital form?
+};
-#define JOYDIR_UP_BIT (1 << JOYDIR_UP)
-#define JOYDIR_DOWN_BIT (1 << JOYDIR_DOWN)
-#define JOYDIR_LEFT_BIT (1 << JOYDIR_LEFT)
-#define JOYDIR_RIGHT_BIT (1 << JOYDIR_RIGHT)
-#define LOG_INPUTX 0
-#define SPACE_COUNT 3
-#define INVALID_CHAR '?'
-#define IP_NAME_DEFAULT NULL
+// live device field information
+class dynamic_field
+{
+ friend class simple_list<dynamic_field>;
+
+public:
+ // construction/destruction
+ dynamic_field(ioport_field &field);
+
+ // getters
+ dynamic_field *next() const { return m_next; }
+ ioport_field &field() const { return m_field; }
+
+ // read/write
+ void read(ioport_value &result);
+ void write(ioport_value newval);
+
+private:
+ // internal state
+ dynamic_field * m_next; // linked list of info for this port
+ ioport_field & m_field; // reference to the input field
+ UINT8 m_shift; // shift to apply to the final result
+ ioport_value m_oldval; // last value
+};
-/***************************************************************************
- TYPE DEFINITIONS
-***************************************************************************/
+// internal live state of an input field
+struct ioport_field_live
+{
+ // construction/destruction
+ ioport_field_live(ioport_field &field, analog_field *analog);
-/* live analog field information */
-typedef struct _analog_field_state analog_field_state;
-struct _analog_field_state
-{
- analog_field_state * next; /* link to the next analog state for this port */
- const input_field_config * field; /* pointer to the input field referenced */
-
- /* adjusted values (right-justified and tweaked) */
- UINT8 shift; /* shift to align final value in the port */
- INT32 adjdefvalue; /* adjusted default value from the config */
- INT32 adjmin; /* adjusted minimum value from the config */
- INT32 adjmax; /* adjusted maximum value from the config */
-
- /* live values of configurable parameters */
- INT32 sensitivity; /* current live sensitivity (100=normal) */
- UINT8 reverse; /* current live reverse flag */
- INT32 delta; /* current live delta to apply each frame a digital inc/dec key is pressed */
- INT32 centerdelta; /* current live delta to apply each frame no digital inputs are pressed */
-
- /* live analog value tracking */
- INT32 accum; /* accumulated value (including relative adjustments) */
- INT32 previous; /* previous adjusted value */
- INT32 previousanalog; /* previous analog value */
-
- /* parameters for modifying live values */
- INT32 minimum; /* minimum adjusted value */
- INT32 maximum; /* maximum adjusted value */
- INT32 center; /* center adjusted value for autocentering */
- INT32 reverse_val; /* value where we subtract from to reverse directions */
-
- /* scaling factors */
- INT64 scalepos; /* scale factor to apply to positive adjusted values */
- INT64 scaleneg; /* scale factor to apply to negative adjusted values */
- INT64 keyscalepos; /* scale factor to apply to the key delta field when pos */
- INT64 keyscaleneg; /* scale factor to apply to the key delta field when neg */
- INT64 positionalscale; /* scale factor to divide a joystick into positions */
-
- /* misc flags */
- UINT8 absolute; /* is this an absolute or relative input? */
- UINT8 wraps; /* does the control wrap around? */
- UINT8 autocenter; /* autocenter this input? */
- UINT8 single_scale; /* scale joystick differently if default is between min/max */
- UINT8 interpolate; /* should we do linear interpolation for mid-frame reads? */
- UINT8 lastdigital; /* was the last modification caused by a digital form? */
+ // public state
+ analog_field * analog; // pointer to live analog data if this is an analog field
+ digital_joystick * joystick; // pointer to digital joystick information
+ input_seq seq[SEQ_TYPE_TOTAL];// currently configured input sequences
+ ioport_value value; // current value of this port
+ UINT8 impulse; // counter for impulse controls
+ bool last; // were we pressed last time?
+ digital_joystick::direction_t joydir; // digital joystick direction index
+ astring name; // overridden name
};
-/* live device field information */
-typedef struct _device_field_info device_field_info;
-struct _device_field_info
+// internal live state of an input port
+struct ioport_port_live
{
- device_field_info * next; /* linked list of info for this port */
- const input_field_config * field; /* pointer to the input field referenced */
- device_t * device; /* device */
- UINT8 shift; /* shift to apply to the final result */
- input_port_value oldval; /* last value */
+ // construction/destruction
+ ioport_port_live(ioport_port &port);
+
+ // public state
+ simple_list<analog_field> analoglist; // list of analog port info
+ simple_list<dynamic_field> readlist; // list of dynamic read fields
+ simple_list<dynamic_field> writelist; // list of dynamic write fields
+ ioport_value defvalue; // combined default value across the port
+ ioport_value digital; // current value from all digital inputs
+ ioport_value outputvalue; // current value for outputs
};
-/* internal live state of an input field */
-struct _input_field_state
+// character information
+struct char_info
{
- analog_field_state * analog; /* pointer to live analog data if this is an analog field */
- digital_joystick_state * joystick; /* pointer to digital joystick information */
- input_seq seq[SEQ_TYPE_TOTAL];/* currently configured input sequences */
- input_port_value value; /* current value of this port */
- UINT8 impulse; /* counter for impulse controls */
- UINT8 last; /* were we pressed last time? */
- UINT8 joydir; /* digital joystick direction index */
- char * name; /* overridden name */
+ unicode_char ch;
+ const char *name;
+ const char *alternate; // alternative string, in UTF-8
+
+ static const char_info *find(unicode_char target);
};
-/* internal live state of an input port */
-struct _input_port_state
-{
- analog_field_state * analoglist; /* pointer to list of analog port info */
- device_field_info * readdevicelist; /* pointer to list of input device info */
- device_field_info * writedevicelist; /* pointer to list of output device info */
- input_port_value defvalue; /* combined default value across the port */
- input_port_value digital; /* current value from all digital inputs */
- input_port_value vblank; /* value of all IPT_VBLANK bits */
- input_port_value outputvalue; /* current value for outputs */
-};
+//**************************************************************************
+// INLINE FUNCTIONS
+//**************************************************************************
-#define KEY_BUFFER_SIZE 4096
+//-------------------------------------------------
+// compute_scale -- compute an 8.24 scale value
+// from a numerator and a denominator
+//-------------------------------------------------
-typedef struct _char_info char_info;
-struct _char_info
+inline INT32 compute_scale(INT32 num, INT32 den)
{
- unicode_char ch;
- const char *name;
- const char *alternate; /* alternative string, in UTF-8 */
-};
+ return (INT64(num) << 24) / den;
+}
-/***************************************************************************
- MACROS
-***************************************************************************/
+//-------------------------------------------------
+// recip_scale -- compute an 8.24 reciprocal of
+// an 8.24 scale value
+//-------------------------------------------------
+
+inline INT32 recip_scale(INT32 scale)
+{
+ return (INT64(1) << 48) / scale;
+}
+
-#define APPLY_SENSITIVITY(x,s) (((INT64)(x) * (s)) / 100.0 + 0.5)
-#define APPLY_INVERSE_SENSITIVITY(x,s) (((INT64)(x) * 100) / (s))
+//-------------------------------------------------
+// apply_scale -- apply an 8.24 scale value to
+// a 32-bit value
+//-------------------------------------------------
-#define COMPUTE_SCALE(num,den) (((INT64)(num) << 24) / (den))
-#define RECIP_SCALE(s) (((INT64)1 << 48) / (s))
-#define APPLY_SCALE(x,s) (((INT64)(x) * (s)) >> 24)
+inline INT32 apply_scale(INT32 value, INT32 scale)
+{
+ return (INT64(value) * scale) >> 24;
+}
-/***************************************************************************
- GLOBAL VARIABLES
-***************************************************************************/
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
-/* XML attributes for the different types */
+// XML attributes for the different types
static const char *const seqtypestrings[] = { "standard", "increment", "decrement" };
-
+// master character info table
static const char_info charinfo[] =
{
- { 0x0008, "Backspace", NULL }, /* Backspace */
- { 0x0009, "Tab", " " }, /* Tab */
- { 0x000c, "Clear", NULL }, /* Clear */
- { 0x000d, "Enter", NULL }, /* Enter */
- { 0x001a, "Esc", NULL }, /* Esc */
- { 0x0020, "Space", " " }, /* Space */
- { 0x0061, NULL, "A" }, /* a */
- { 0x0062, NULL, "B" }, /* b */
- { 0x0063, NULL, "C" }, /* c */
- { 0x0064, NULL, "D" }, /* d */
- { 0x0065, NULL, "E" }, /* e */
- { 0x0066, NULL, "F" }, /* f */
- { 0x0067, NULL, "G" }, /* g */
- { 0x0068, NULL, "H" }, /* h */
- { 0x0069, NULL, "I" }, /* i */
- { 0x006a, NULL, "J" }, /* j */
- { 0x006b, NULL, "K" }, /* k */
- { 0x006c, NULL, "L" }, /* l */
- { 0x006d, NULL, "M" }, /* m */
- { 0x006e, NULL, "N" }, /* n */
- { 0x006f, NULL, "O" }, /* o */
- { 0x0070, NULL, "P" }, /* p */
- { 0x0071, NULL, "Q" }, /* q */
- { 0x0072, NULL, "R" }, /* r */
- { 0x0073, NULL, "S" }, /* s */
- { 0x0074, NULL, "T" }, /* t */
- { 0x0075, NULL, "U" }, /* u */
- { 0x0076, NULL, "V" }, /* v */
- { 0x0077, NULL, "W" }, /* w */
- { 0x0078, NULL, "X" }, /* x */
- { 0x0079, NULL, "Y" }, /* y */
- { 0x007a, NULL, "Z" }, /* z */
- { 0x00a0, NULL, " " }, /* non breaking space */
- { 0x00a1, NULL, "!" }, /* inverted exclaimation mark */
- { 0x00a6, NULL, "|" }, /* broken bar */
- { 0x00a9, NULL, "(c)" }, /* copyright sign */
- { 0x00ab, NULL, "<<" }, /* left pointing double angle */
- { 0x00ae, NULL, "(r)" }, /* registered sign */
- { 0x00bb, NULL, ">>" }, /* right pointing double angle */
- { 0x00bc, NULL, "1/4" }, /* vulgar fraction one quarter */
- { 0x00bd, NULL, "1/2" }, /* vulgar fraction one half */
- { 0x00be, NULL, "3/4" }, /* vulgar fraction three quarters */
- { 0x00bf, NULL, "?" }, /* inverted question mark */
- { 0x00c0, NULL, "A" }, /* 'A' grave */
- { 0x00c1, NULL, "A" }, /* 'A' acute */
- { 0x00c2, NULL, "A" }, /* 'A' circumflex */
- { 0x00c3, NULL, "A" }, /* 'A' tilde */
- { 0x00c4, NULL, "A" }, /* 'A' diaeresis */
- { 0x00c5, NULL, "A" }, /* 'A' ring above */
- { 0x00c6, NULL, "AE" }, /* 'AE' ligature */
- { 0x00c7, NULL, "C" }, /* 'C' cedilla */
- { 0x00c8, NULL, "E" }, /* 'E' grave */
- { 0x00c9, NULL, "E" }, /* 'E' acute */
- { 0x00ca, NULL, "E" }, /* 'E' circumflex */
- { 0x00cb, NULL, "E" }, /* 'E' diaeresis */
- { 0x00cc, NULL, "I" }, /* 'I' grave */
- { 0x00cd, NULL, "I" }, /* 'I' acute */
- { 0x00ce, NULL, "I" }, /* 'I' circumflex */
- { 0x00cf, NULL, "I" }, /* 'I' diaeresis */
- { 0x00d0, NULL, "D" }, /* 'ETH' */
- { 0x00d1, NULL, "N" }, /* 'N' tilde */
- { 0x00d2, NULL, "O" }, /* 'O' grave */
- { 0x00d3, NULL, "O" }, /* 'O' acute */
- { 0x00d4, NULL, "O" }, /* 'O' circumflex */
- { 0x00d5, NULL, "O" }, /* 'O' tilde */
- { 0x00d6, NULL, "O" }, /* 'O' diaeresis */
- { 0x00d7, NULL, "X" }, /* multiplication sign */
- { 0x00d8, NULL, "O" }, /* 'O' stroke */
- { 0x00d9, NULL, "U" }, /* 'U' grave */
- { 0x00da, NULL, "U" }, /* 'U' acute */
- { 0x00db, NULL, "U" }, /* 'U' circumflex */
- { 0x00dc, NULL, "U" }, /* 'U' diaeresis */
- { 0x00dd, NULL, "Y" }, /* 'Y' acute */
- { 0x00df, NULL, "SS" }, /* sharp S */
- { 0x00e0, NULL, "a" }, /* 'a' grave */
- { 0x00e1, NULL, "a" }, /* 'a' acute */
- { 0x00e2, NULL, "a" }, /* 'a' circumflex */
- { 0x00e3, NULL, "a" }, /* 'a' tilde */
- { 0x00e4, NULL, "a" }, /* 'a' diaeresis */
- { 0x00e5, NULL, "a" }, /* 'a' ring above */
- { 0x00e6, NULL, "ae" }, /* 'ae' ligature */
- { 0x00e7, NULL, "c" }, /* 'c' cedilla */
- { 0x00e8, NULL, "e" }, /* 'e' grave */
- { 0x00e9, NULL, "e" }, /* 'e' acute */
- { 0x00ea, NULL, "e" }, /* 'e' circumflex */
- { 0x00eb, NULL, "e" }, /* 'e' diaeresis */
- { 0x00ec, NULL, "i" }, /* 'i' grave */
- { 0x00ed, NULL, "i" }, /* 'i' acute */
- { 0x00ee, NULL, "i" }, /* 'i' circumflex */
- { 0x00ef, NULL, "i" }, /* 'i' diaeresis */
- { 0x00f0, NULL, "d" }, /* 'eth' */
- { 0x00f1, NULL, "n" }, /* 'n' tilde */
- { 0x00f2, NULL, "o" }, /* 'o' grave */
- { 0x00f3, NULL, "o" }, /* 'o' acute */
- { 0x00f4, NULL, "o" }, /* 'o' circumflex */
- { 0x00f5, NULL, "o" }, /* 'o' tilde */
- { 0x00f6, NULL, "o" }, /* 'o' diaeresis */
- { 0x00f8, NULL, "o" }, /* 'o' stroke */
- { 0x00f9, NULL, "u" }, /* 'u' grave */
- { 0x00fa, NULL, "u" }, /* 'u' acute */
- { 0x00fb, NULL, "u" }, /* 'u' circumflex */
- { 0x00fc, NULL, "u" }, /* 'u' diaeresis */
- { 0x00fd, NULL, "y" }, /* 'y' acute */
- { 0x00ff, NULL, "y" }, /* 'y' diaeresis */
- { 0x2010, NULL, "-" }, /* hyphen */
- { 0x2011, NULL, "-" }, /* non-breaking hyphen */
- { 0x2012, NULL, "-" }, /* figure dash */
- { 0x2013, NULL, "-" }, /* en dash */
- { 0x2014, NULL, "-" }, /* em dash */
- { 0x2015, NULL, "-" }, /* horizontal dash */
- { 0x2018, NULL, "\'" }, /* left single quotation mark */
- { 0x2019, NULL, "\'" }, /* right single quotation mark */
- { 0x201a, NULL, "\'" }, /* single low quotation mark */
- { 0x201b, NULL, "\'" }, /* single high reversed quotation mark */
- { 0x201c, NULL, "\"" }, /* left double quotation mark */
- { 0x201d, NULL, "\"" }, /* right double quotation mark */
- { 0x201e, NULL, "\"" }, /* double low quotation mark */
- { 0x201f, NULL, "\"" }, /* double high reversed quotation mark */
- { 0x2024, NULL, "." }, /* one dot leader */
- { 0x2025, NULL, ".." }, /* two dot leader */
- { 0x2026, NULL, "..." }, /* horizontal ellipsis */
- { 0x2047, NULL, "??" }, /* double question mark */
- { 0x2048, NULL, "?!" }, /* question exclamation mark */
- { 0x2049, NULL, "!?" }, /* exclamation question mark */
- { 0xff01, NULL, "!" }, /* fullwidth exclamation point */
- { 0xff02, NULL, "\"" }, /* fullwidth quotation mark */
- { 0xff03, NULL, "#" }, /* fullwidth number sign */
- { 0xff04, NULL, "$" }, /* fullwidth dollar sign */
- { 0xff05, NULL, "%" }, /* fullwidth percent sign */
- { 0xff06, NULL, "&" }, /* fullwidth ampersand */
- { 0xff07, NULL, "\'" }, /* fullwidth apostrophe */
- { 0xff08, NULL, "(" }, /* fullwidth left parenthesis */
- { 0xff09, NULL, ")" }, /* fullwidth right parenthesis */
- { 0xff0a, NULL, "*" }, /* fullwidth asterisk */
- { 0xff0b, NULL, "+" }, /* fullwidth plus */
- { 0xff0c, NULL, "," }, /* fullwidth comma */
- { 0xff0d, NULL, "-" }, /* fullwidth minus */
- { 0xff0e, NULL, "." }, /* fullwidth period */
- { 0xff0f, NULL, "/" }, /* fullwidth slash */
- { 0xff10, NULL, "0" }, /* fullwidth zero */
- { 0xff11, NULL, "1" }, /* fullwidth one */
- { 0xff12, NULL, "2" }, /* fullwidth two */
- { 0xff13, NULL, "3" }, /* fullwidth three */
- { 0xff14, NULL, "4" }, /* fullwidth four */
- { 0xff15, NULL, "5" }, /* fullwidth five */
- { 0xff16, NULL, "6" }, /* fullwidth six */
- { 0xff17, NULL, "7" }, /* fullwidth seven */
- { 0xff18, NULL, "8" }, /* fullwidth eight */
- { 0xff19, NULL, "9" }, /* fullwidth nine */
- { 0xff1a, NULL, ":" }, /* fullwidth colon */
- { 0xff1b, NULL, ";" }, /* fullwidth semicolon */
- { 0xff1c, NULL, "<" }, /* fullwidth less than sign */
- { 0xff1d, NULL, "=" }, /* fullwidth equals sign */
- { 0xff1e, NULL, ">" }, /* fullwidth greater than sign */
- { 0xff1f, NULL, "?" }, /* fullwidth question mark */
- { 0xff20, NULL, "@" }, /* fullwidth at sign */
- { 0xff21, NULL, "A" }, /* fullwidth 'A' */
- { 0xff22, NULL, "B" }, /* fullwidth 'B' */
- { 0xff23, NULL, "C" }, /* fullwidth 'C' */
- { 0xff24, NULL, "D" }, /* fullwidth 'D' */
- { 0xff25, NULL, "E" }, /* fullwidth 'E' */
- { 0xff26, NULL, "F" }, /* fullwidth 'F' */
- { 0xff27, NULL, "G" }, /* fullwidth 'G' */
- { 0xff28, NULL, "H" }, /* fullwidth 'H' */
- { 0xff29, NULL, "I" }, /* fullwidth 'I' */
- { 0xff2a, NULL, "J" }, /* fullwidth 'J' */
- { 0xff2b, NULL, "K" }, /* fullwidth 'K' */
- { 0xff2c, NULL, "L" }, /* fullwidth 'L' */
- { 0xff2d, NULL, "M" }, /* fullwidth 'M' */
- { 0xff2e, NULL, "N" }, /* fullwidth 'N' */
- { 0xff2f, NULL, "O" }, /* fullwidth 'O' */
- { 0xff30, NULL, "P" }, /* fullwidth 'P' */
- { 0xff31, NULL, "Q" }, /* fullwidth 'Q' */
- { 0xff32, NULL, "R" }, /* fullwidth 'R' */
- { 0xff33, NULL, "S" }, /* fullwidth 'S' */
- { 0xff34, NULL, "T" }, /* fullwidth 'T' */
- { 0xff35, NULL, "U" }, /* fullwidth 'U' */
- { 0xff36, NULL, "V" }, /* fullwidth 'V' */
- { 0xff37, NULL, "W" }, /* fullwidth 'W' */
- { 0xff38, NULL, "X" }, /* fullwidth 'X' */
- { 0xff39, NULL, "Y" }, /* fullwidth 'Y' */
- { 0xff3a, NULL, "Z" }, /* fullwidth 'Z' */
- { 0xff3b, NULL, "[" }, /* fullwidth left bracket */
- { 0xff3c, NULL, "\\" }, /* fullwidth backslash */
- { 0xff3d, NULL, "]" }, /* fullwidth right bracket */
- { 0xff3e, NULL, "^" }, /* fullwidth caret */
- { 0xff3f, NULL, "_" }, /* fullwidth underscore */
- { 0xff40, NULL, "`" }, /* fullwidth backquote */
- { 0xff41, NULL, "a" }, /* fullwidth 'a' */
- { 0xff42, NULL, "b" }, /* fullwidth 'b' */
- { 0xff43, NULL, "c" }, /* fullwidth 'c' */
- { 0xff44, NULL, "d" }, /* fullwidth 'd' */
- { 0xff45, NULL, "e" }, /* fullwidth 'e' */
- { 0xff46, NULL, "f" }, /* fullwidth 'f' */
- { 0xff47, NULL, "g" }, /* fullwidth 'g' */
- { 0xff48, NULL, "h" }, /* fullwidth 'h' */
- { 0xff49, NULL, "i" }, /* fullwidth 'i' */
- { 0xff4a, NULL, "j" }, /* fullwidth 'j' */
- { 0xff4b, NULL, "k" }, /* fullwidth 'k' */
- { 0xff4c, NULL, "l" }, /* fullwidth 'l' */
- { 0xff4d, NULL, "m" }, /* fullwidth 'm' */
- { 0xff4e, NULL, "n" }, /* fullwidth 'n' */
- { 0xff4f, NULL, "o" }, /* fullwidth 'o' */
- { 0xff50, NULL, "p" }, /* fullwidth 'p' */
- { 0xff51, NULL, "q" }, /* fullwidth 'q' */
- { 0xff52, NULL, "r" }, /* fullwidth 'r' */
- { 0xff53, NULL, "s" }, /* fullwidth 's' */
- { 0xff54, NULL, "t" }, /* fullwidth 't' */
- { 0xff55, NULL, "u" }, /* fullwidth 'u' */
- { 0xff56, NULL, "v" }, /* fullwidth 'v' */
- { 0xff57, NULL, "w" }, /* fullwidth 'w' */
- { 0xff58, NULL, "x" }, /* fullwidth 'x' */
- { 0xff59, NULL, "y" }, /* fullwidth 'y' */
- { 0xff5a, NULL, "z" }, /* fullwidth 'z' */
- { 0xff5b, NULL, "{" }, /* fullwidth left brace */
- { 0xff5c, NULL, "|" }, /* fullwidth vertical bar */
- { 0xff5d, NULL, "}" }, /* fullwidth right brace */
- { 0xff5e, NULL, "~" }, /* fullwidth tilde */
- { 0xff5f, NULL, "((" }, /* fullwidth double left parenthesis */
- { 0xff60, NULL, "))" }, /* fullwidth double right parenthesis */
- { 0xffe0, NULL, "\xC2\xA2" }, /* fullwidth cent sign */
- { 0xffe1, NULL, "\xC2\xA3" }, /* fullwidth pound sign */
- { 0xffe4, NULL, "\xC2\xA4" }, /* fullwidth broken bar */
- { 0xffe5, NULL, "\xC2\xA5" }, /* fullwidth yen sign */
- { 0xffe6, NULL, "\xE2\x82\xA9" }, /* fullwidth won sign */
- { 0xffe9, NULL, "\xE2\x86\x90" }, /* fullwidth left arrow */
- { 0xffea, NULL, "\xE2\x86\x91" }, /* fullwidth up arrow */
- { 0xffeb, NULL, "\xE2\x86\x92" }, /* fullwidth right arrow */
- { 0xffec, NULL, "\xE2\x86\x93" }, /* fullwidth down arrow */
- { 0xffed, NULL, "\xE2\x96\xAA" }, /* fullwidth solid box */
- { 0xffee, NULL, "\xE2\x97\xA6" }, /* fullwidth open circle */
- { UCHAR_SHIFT_1, "Shift", NULL }, /* Shift key */
- { UCHAR_SHIFT_2, "Ctrl", NULL }, /* Ctrl key */
- { UCHAR_MAMEKEY(F1), "F1", NULL }, /* F1 function key */
- { UCHAR_MAMEKEY(F2), "F2", NULL }, /* F2 function key */
- { UCHAR_MAMEKEY(F3), "F3", NULL }, /* F3 function key */
- { UCHAR_MAMEKEY(F4), "F4", NULL }, /* F4 function key */
- { UCHAR_MAMEKEY(F5), "F5", NULL }, /* F5 function key */
- { UCHAR_MAMEKEY(F6), "F6", NULL }, /* F6 function key */
- { UCHAR_MAMEKEY(F7), "F7", NULL }, /* F7 function key */
- { UCHAR_MAMEKEY(F8), "F8", NULL }, /* F8 function key */
- { UCHAR_MAMEKEY(F9), "F9", NULL }, /* F9 function key */
- { UCHAR_MAMEKEY(F10), "F10", NULL }, /* F10 function key */
- { UCHAR_MAMEKEY(F11), "F11", NULL }, /* F11 function key */
- { UCHAR_MAMEKEY(F12), "F12", NULL }, /* F12 function key */
- { UCHAR_MAMEKEY(F13), "F13", NULL }, /* F13 function key */
- { UCHAR_MAMEKEY(F14), "F14", NULL }, /* F14 function key */
- { UCHAR_MAMEKEY(F15), "F15", NULL }, /* F15 function key */
- { UCHAR_MAMEKEY(ESC), "Esc", "\033" }, /* Esc key */
- { UCHAR_MAMEKEY(INSERT), "Insert", NULL }, /* Insert key */
- { UCHAR_MAMEKEY(DEL), "Delete", "\010" }, /* Delete key */
- { UCHAR_MAMEKEY(HOME), "Home", "\014" }, /* Home key */
- { UCHAR_MAMEKEY(END), "End", NULL }, /* End key */
- { UCHAR_MAMEKEY(PGUP), "Page Up", NULL }, /* Page Up key */
- { UCHAR_MAMEKEY(PGDN), "Page Down", NULL }, /* Page Down key */
- { UCHAR_MAMEKEY(LEFT), "Cursor Left", NULL }, /* Cursor Left */
- { UCHAR_MAMEKEY(RIGHT), "Cursor Right", NULL }, /* Cursor Right */
- { UCHAR_MAMEKEY(UP), "Cursor Up", NULL }, /* Cursor Up */
- { UCHAR_MAMEKEY(DOWN), "Cursor Down", NULL }, /* Cursor Down */
- { UCHAR_MAMEKEY(0_PAD), "Keypad 0", NULL }, /* 0 on the numeric keypad */
- { UCHAR_MAMEKEY(1_PAD), "Keypad 1", NULL }, /* 1 on the numeric keypad */
- { UCHAR_MAMEKEY(2_PAD), "Keypad 2", NULL }, /* 2 on the numeric keypad */
- { UCHAR_MAMEKEY(3_PAD), "Keypad 3", NULL }, /* 3 on the numeric keypad */
- { UCHAR_MAMEKEY(4_PAD), "Keypad 4", NULL }, /* 4 on the numeric keypad */
- { UCHAR_MAMEKEY(5_PAD), "Keypad 5", NULL }, /* 5 on the numeric keypad */
- { UCHAR_MAMEKEY(6_PAD), "Keypad 6", NULL }, /* 6 on the numeric keypad */
- { UCHAR_MAMEKEY(7_PAD), "Keypad 7", NULL }, /* 7 on the numeric keypad */
- { UCHAR_MAMEKEY(8_PAD), "Keypad 8", NULL }, /* 8 on the numeric keypad */
- { UCHAR_MAMEKEY(9_PAD), "Keypad 9", NULL }, /* 9 on the numeric keypad */
- { UCHAR_MAMEKEY(SLASH_PAD), "Keypad /", NULL }, /* / on the numeric keypad */
- { UCHAR_MAMEKEY(ASTERISK), "Keypad *", NULL }, /* * on the numeric keypad */
- { UCHAR_MAMEKEY(MINUS_PAD), "Keypad -", NULL }, /* - on the numeric Keypad */
- { UCHAR_MAMEKEY(PLUS_PAD), "Keypad +", NULL }, /* + on the numeric Keypad */
- { UCHAR_MAMEKEY(DEL_PAD), "Keypad .", NULL }, /* . on the numeric keypad */
- { UCHAR_MAMEKEY(ENTER_PAD), "Keypad Enter", NULL }, /* Enter on the numeric keypad */
- { UCHAR_MAMEKEY(PRTSCR), "Print Screen", NULL }, /* Print Screen key */
- { UCHAR_MAMEKEY(PAUSE), "Pause", NULL }, /* Pause key */
- { UCHAR_MAMEKEY(LSHIFT), "Left Shift", NULL }, /* Left Shift key */
- { UCHAR_MAMEKEY(RSHIFT), "Right Shift", NULL }, /* Right Shift key */
- { UCHAR_MAMEKEY(LCONTROL), "Left Ctrl", NULL }, /* Left Control key */
- { UCHAR_MAMEKEY(RCONTROL), "Right Ctrl", NULL }, /* Right Control key */
- { UCHAR_MAMEKEY(LALT), "Left Alt", NULL }, /* Left Alt key */
- { UCHAR_MAMEKEY(RALT), "Right Alt", NULL }, /* Right Alt key */
- { UCHAR_MAMEKEY(SCRLOCK), "Scroll Lock", NULL }, /* Scroll Lock key */
- { UCHAR_MAMEKEY(NUMLOCK), "Num Lock", NULL }, /* Num Lock key */
- { UCHAR_MAMEKEY(CAPSLOCK), "Caps Lock", NULL }, /* Caps Lock key */
- { UCHAR_MAMEKEY(LWIN), "Left Win", NULL }, /* Left Win key */
- { UCHAR_MAMEKEY(RWIN), "Right Win", NULL }, /* Right Win key */
- { UCHAR_MAMEKEY(MENU), "Menu", NULL }, /* Menu key */
- { UCHAR_MAMEKEY(CANCEL), "Break", NULL } /* Break/Pause key */
+ { 0x0008, "Backspace", NULL }, // Backspace
+ { 0x0009, "Tab", " " }, // Tab
+ { 0x000c, "Clear", NULL }, // Clear
+ { 0x000d, "Enter", NULL }, // Enter
+ { 0x001a, "Esc", NULL }, // Esc
+ { 0x0020, "Space", " " }, // Space
+ { 0x0061, NULL, "A" }, // a
+ { 0x0062, NULL, "B" }, // b
+ { 0x0063, NULL, "C" }, // c
+ { 0x0064, NULL, "D" }, // d
+ { 0x0065, NULL, "E" }, // e
+ { 0x0066, NULL, "F" }, // f
+ { 0x0067, NULL, "G" }, // g
+ { 0x0068, NULL, "H" }, // h
+ { 0x0069, NULL, "I" }, // i
+ { 0x006a, NULL, "J" }, // j
+ { 0x006b, NULL, "K" }, // k
+ { 0x006c, NULL, "L" }, // l
+ { 0x006d, NULL, "M" }, // m
+ { 0x006e, NULL, "N" }, // n
+ { 0x006f, NULL, "O" }, // o
+ { 0x0070, NULL, "P" }, // p
+ { 0x0071, NULL, "Q" }, // q
+ { 0x0072, NULL, "R" }, // r
+ { 0x0073, NULL, "S" }, // s
+ { 0x0074, NULL, "T" }, // t
+ { 0x0075, NULL, "U" }, // u
+ { 0x0076, NULL, "V" }, // v
+ { 0x0077, NULL, "W" }, // w
+ { 0x0078, NULL, "X" }, // x
+ { 0x0079, NULL, "Y" }, // y
+ { 0x007a, NULL, "Z" }, // z
+ { 0x00a0, NULL, " " }, // non breaking space
+ { 0x00a1, NULL, "!" }, // inverted exclaimation mark
+ { 0x00a6, NULL, "|" }, // broken bar
+ { 0x00a9, NULL, "(c)" }, // copyright sign
+ { 0x00ab, NULL, "<<" }, // left pointing double angle
+ { 0x00ae, NULL, "(r)" }, // registered sign
+ { 0x00bb, NULL, ">>" }, // right pointing double angle
+ { 0x00bc, NULL, "1/4" }, // vulgar fraction one quarter
+ { 0x00bd, NULL, "1/2" }, // vulgar fraction one half
+ { 0x00be, NULL, "3/4" }, // vulgar fraction three quarters
+ { 0x00bf, NULL, "?" }, // inverted question mark
+ { 0x00c0, NULL, "A" }, // 'A' grave
+ { 0x00c1, NULL, "A" }, // 'A' acute
+ { 0x00c2, NULL, "A" }, // 'A' circumflex
+ { 0x00c3, NULL, "A" }, // 'A' tilde
+ { 0x00c4, NULL, "A" }, // 'A' diaeresis
+ { 0x00c5, NULL, "A" }, // 'A' ring above
+ { 0x00c6, NULL, "AE" }, // 'AE' ligature
+ { 0x00c7, NULL, "C" }, // 'C' cedilla
+ { 0x00c8, NULL, "E" }, // 'E' grave
+ { 0x00c9, NULL, "E" }, // 'E' acute
+ { 0x00ca, NULL, "E" }, // 'E' circumflex
+ { 0x00cb, NULL, "E" }, // 'E' diaeresis
+ { 0x00cc, NULL, "I" }, // 'I' grave
+ { 0x00cd, NULL, "I" }, // 'I' acute
+ { 0x00ce, NULL, "I" }, // 'I' circumflex
+ { 0x00cf, NULL, "I" }, // 'I' diaeresis
+ { 0x00d0, NULL, "D" }, // 'ETH'
+ { 0x00d1, NULL, "N" }, // 'N' tilde
+ { 0x00d2, NULL, "O" }, // 'O' grave
+ { 0x00d3, NULL, "O" }, // 'O' acute
+ { 0x00d4, NULL, "O" }, // 'O' circumflex
+ { 0x00d5, NULL, "O" }, // 'O' tilde
+ { 0x00d6, NULL, "O" }, // 'O' diaeresis
+ { 0x00d7, NULL, "X" }, // multiplication sign
+ { 0x00d8, NULL, "O" }, // 'O' stroke
+ { 0x00d9, NULL, "U" }, // 'U' grave
+ { 0x00da, NULL, "U" }, // 'U' acute
+ { 0x00db, NULL, "U" }, // 'U' circumflex
+ { 0x00dc, NULL, "U" }, // 'U' diaeresis
+ { 0x00dd, NULL, "Y" }, // 'Y' acute
+ { 0x00df, NULL, "SS" }, // sharp S
+ { 0x00e0, NULL, "a" }, // 'a' grave
+ { 0x00e1, NULL, "a" }, // 'a' acute
+ { 0x00e2, NULL, "a" }, // 'a' circumflex
+ { 0x00e3, NULL, "a" }, // 'a' tilde
+ { 0x00e4, NULL, "a" }, // 'a' diaeresis
+ { 0x00e5, NULL, "a" }, // 'a' ring above
+ { 0x00e6, NULL, "ae" }, // 'ae' ligature
+ { 0x00e7, NULL, "c" }, // 'c' cedilla
+ { 0x00e8, NULL, "e" }, // 'e' grave
+ { 0x00e9, NULL, "e" }, // 'e' acute
+ { 0x00ea, NULL, "e" }, // 'e' circumflex
+ { 0x00eb, NULL, "e" }, // 'e' diaeresis
+ { 0x00ec, NULL, "i" }, // 'i' grave
+ { 0x00ed, NULL, "i" }, // 'i' acute
+ { 0x00ee, NULL, "i" }, // 'i' circumflex
+ { 0x00ef, NULL, "i" }, // 'i' diaeresis
+ { 0x00f0, NULL, "d" }, // 'eth'
+ { 0x00f1, NULL, "n" }, // 'n' tilde
+ { 0x00f2, NULL, "o" }, // 'o' grave
+ { 0x00f3, NULL, "o" }, // 'o' acute
+ { 0x00f4, NULL, "o" }, // 'o' circumflex
+ { 0x00f5, NULL, "o" }, // 'o' tilde
+ { 0x00f6, NULL, "o" }, // 'o' diaeresis
+ { 0x00f8, NULL, "o" }, // 'o' stroke
+ { 0x00f9, NULL, "u" }, // 'u' grave
+ { 0x00fa, NULL, "u" }, // 'u' acute
+ { 0x00fb, NULL, "u" }, // 'u' circumflex
+ { 0x00fc, NULL, "u" }, // 'u' diaeresis
+ { 0x00fd, NULL, "y" }, // 'y' acute
+ { 0x00ff, NULL, "y" }, // 'y' diaeresis
+ { 0x2010, NULL, "-" }, // hyphen
+ { 0x2011, NULL, "-" }, // non-breaking hyphen
+ { 0x2012, NULL, "-" }, // figure dash
+ { 0x2013, NULL, "-" }, // en dash
+ { 0x2014, NULL, "-" }, // em dash
+ { 0x2015, NULL, "-" }, // horizontal dash
+ { 0x2018, NULL, "\'" }, // left single quotation mark
+ { 0x2019, NULL, "\'" }, // right single quotation mark
+ { 0x201a, NULL, "\'" }, // single low quotation mark
+ { 0x201b, NULL, "\'" }, // single high reversed quotation mark
+ { 0x201c, NULL, "\"" }, // left double quotation mark
+ { 0x201d, NULL, "\"" }, // right double quotation mark
+ { 0x201e, NULL, "\"" }, // double low quotation mark
+ { 0x201f, NULL, "\"" }, // double high reversed quotation mark
+ { 0x2024, NULL, "." }, // one dot leader
+ { 0x2025, NULL, ".." }, // two dot leader
+ { 0x2026, NULL, "..." }, // horizontal ellipsis
+ { 0x2047, NULL, "??" }, // double question mark
+ { 0x2048, NULL, "?!" }, // question exclamation mark
+ { 0x2049, NULL, "!?" }, // exclamation question mark
+ { 0xff01, NULL, "!" }, // fullwidth exclamation point
+ { 0xff02, NULL, "\"" }, // fullwidth quotation mark
+ { 0xff03, NULL, "#" }, // fullwidth number sign
+ { 0xff04, NULL, "$" }, // fullwidth dollar sign
+ { 0xff05, NULL, "%" }, // fullwidth percent sign
+ { 0xff06, NULL, "&" }, // fullwidth ampersand
+ { 0xff07, NULL, "\'" }, // fullwidth apostrophe
+ { 0xff08, NULL, "(" }, // fullwidth left parenthesis
+ { 0xff09, NULL, ")" }, // fullwidth right parenthesis
+ { 0xff0a, NULL, "*" }, // fullwidth asterisk
+ { 0xff0b, NULL, "+" }, // fullwidth plus
+ { 0xff0c, NULL, "," }, // fullwidth comma
+ { 0xff0d, NULL, "-" }, // fullwidth minus
+ { 0xff0e, NULL, "." }, // fullwidth period
+ { 0xff0f, NULL, "/" }, // fullwidth slash
+ { 0xff10, NULL, "0" }, // fullwidth zero
+ { 0xff11, NULL, "1" }, // fullwidth one
+ { 0xff12, NULL, "2" }, // fullwidth two
+ { 0xff13, NULL, "3" }, // fullwidth three
+ { 0xff14, NULL, "4" }, // fullwidth four
+ { 0xff15, NULL, "5" }, // fullwidth five
+ { 0xff16, NULL, "6" }, // fullwidth six
+ { 0xff17, NULL, "7" }, // fullwidth seven
+ { 0xff18, NULL, "8" }, // fullwidth eight
+ { 0xff19, NULL, "9" }, // fullwidth nine
+ { 0xff1a, NULL, ":" }, // fullwidth colon
+ { 0xff1b, NULL, ";" }, // fullwidth semicolon
+ { 0xff1c, NULL, "<" }, // fullwidth less than sign
+ { 0xff1d, NULL, "=" }, // fullwidth equals sign
+ { 0xff1e, NULL, ">" }, // fullwidth greater than sign
+ { 0xff1f, NULL, "?" }, // fullwidth question mark
+ { 0xff20, NULL, "@" }, // fullwidth at sign
+ { 0xff21, NULL, "A" }, // fullwidth 'A'
+ { 0xff22, NULL, "B" }, // fullwidth 'B'
+ { 0xff23, NULL, "C" }, // fullwidth 'C'
+ { 0xff24, NULL, "D" }, // fullwidth 'D'
+ { 0xff25, NULL, "E" }, // fullwidth 'E'
+ { 0xff26, NULL, "F" }, // fullwidth 'F'
+ { 0xff27, NULL, "G" }, // fullwidth 'G'
+ { 0xff28, NULL, "H" }, // fullwidth 'H'
+ { 0xff29, NULL, "I" }, // fullwidth 'I'
+ { 0xff2a, NULL, "J" }, // fullwidth 'J'
+ { 0xff2b, NULL, "K" }, // fullwidth 'K'
+ { 0xff2c, NULL, "L" }, // fullwidth 'L'
+ { 0xff2d, NULL, "M" }, // fullwidth 'M'
+ { 0xff2e, NULL, "N" }, // fullwidth 'N'
+ { 0xff2f, NULL, "O" }, // fullwidth 'O'
+ { 0xff30, NULL, "P" }, // fullwidth 'P'
+ { 0xff31, NULL, "Q" }, // fullwidth 'Q'
+ { 0xff32, NULL, "R" }, // fullwidth 'R'
+ { 0xff33, NULL, "S" }, // fullwidth 'S'
+ { 0xff34, NULL, "T" }, // fullwidth 'T'
+ { 0xff35, NULL, "U" }, // fullwidth 'U'
+ { 0xff36, NULL, "V" }, // fullwidth 'V'
+ { 0xff37, NULL, "W" }, // fullwidth 'W'
+ { 0xff38, NULL, "X" }, // fullwidth 'X'
+ { 0xff39, NULL, "Y" }, // fullwidth 'Y'
+ { 0xff3a, NULL, "Z" }, // fullwidth 'Z'
+ { 0xff3b, NULL, "[" }, // fullwidth left bracket
+ { 0xff3c, NULL, "\\" }, // fullwidth backslash
+ { 0xff3d, NULL, "]" }, // fullwidth right bracket
+ { 0xff3e, NULL, "^" }, // fullwidth caret
+ { 0xff3f, NULL, "_" }, // fullwidth underscore
+ { 0xff40, NULL, "`" }, // fullwidth backquote
+ { 0xff41, NULL, "a" }, // fullwidth 'a'
+ { 0xff42, NULL, "b" }, // fullwidth 'b'
+ { 0xff43, NULL, "c" }, // fullwidth 'c'
+ { 0xff44, NULL, "d" }, // fullwidth 'd'
+ { 0xff45, NULL, "e" }, // fullwidth 'e'
+ { 0xff46, NULL, "f" }, // fullwidth 'f'
+ { 0xff47, NULL, "g" }, // fullwidth 'g'
+ { 0xff48, NULL, "h" }, // fullwidth 'h'
+ { 0xff49, NULL, "i" }, // fullwidth 'i'
+ { 0xff4a, NULL, "j" }, // fullwidth 'j'
+ { 0xff4b, NULL, "k" }, // fullwidth 'k'
+ { 0xff4c, NULL, "l" }, // fullwidth 'l'
+ { 0xff4d, NULL, "m" }, // fullwidth 'm'
+ { 0xff4e, NULL, "n" }, // fullwidth 'n'
+ { 0xff4f, NULL, "o" }, // fullwidth 'o'
+ { 0xff50, NULL, "p" }, // fullwidth 'p'
+ { 0xff51, NULL, "q" }, // fullwidth 'q'
+ { 0xff52, NULL, "r" }, // fullwidth 'r'
+ { 0xff53, NULL, "s" }, // fullwidth 's'
+ { 0xff54, NULL, "t" }, // fullwidth 't'
+ { 0xff55, NULL, "u" }, // fullwidth 'u'
+ { 0xff56, NULL, "v" }, // fullwidth 'v'
+ { 0xff57, NULL, "w" }, // fullwidth 'w'
+ { 0xff58, NULL, "x" }, // fullwidth 'x'
+ { 0xff59, NULL, "y" }, // fullwidth 'y'
+ { 0xff5a, NULL, "z" }, // fullwidth 'z'
+ { 0xff5b, NULL, "{" }, // fullwidth left brace
+ { 0xff5c, NULL, "|" }, // fullwidth vertical bar
+ { 0xff5d, NULL, "}" }, // fullwidth right brace
+ { 0xff5e, NULL, "~" }, // fullwidth tilde
+ { 0xff5f, NULL, "((" }, // fullwidth double left parenthesis
+ { 0xff60, NULL, "))" }, // fullwidth double right parenthesis
+ { 0xffe0, NULL, "\xC2\xA2" }, // fullwidth cent sign
+ { 0xffe1, NULL, "\xC2\xA3" }, // fullwidth pound sign
+ { 0xffe4, NULL, "\xC2\xA4" }, // fullwidth broken bar
+ { 0xffe5, NULL, "\xC2\xA5" }, // fullwidth yen sign
+ { 0xffe6, NULL, "\xE2\x82\xA9" }, // fullwidth won sign
+ { 0xffe9, NULL, "\xE2\x86\x90" }, // fullwidth left arrow
+ { 0xffea, NULL, "\xE2\x86\x91" }, // fullwidth up arrow
+ { 0xffeb, NULL, "\xE2\x86\x92" }, // fullwidth right arrow
+ { 0xffec, NULL, "\xE2\x86\x93" }, // fullwidth down arrow
+ { 0xffed, NULL, "\xE2\x96\xAA" }, // fullwidth solid box
+ { 0xffee, NULL, "\xE2\x97\xA6" }, // fullwidth open circle
+ { UCHAR_SHIFT_1, "Shift", NULL }, // Shift key
+ { UCHAR_SHIFT_2, "Ctrl", NULL }, // Ctrl key
+ { UCHAR_MAMEKEY(F1), "F1", NULL }, // F1 function key
+ { UCHAR_MAMEKEY(F2), "F2", NULL }, // F2 function key
+ { UCHAR_MAMEKEY(F3), "F3", NULL }, // F3 function key
+ { UCHAR_MAMEKEY(F4), "F4", NULL }, // F4 function key
+ { UCHAR_MAMEKEY(F5), "F5", NULL }, // F5 function key
+ { UCHAR_MAMEKEY(F6), "F6", NULL }, // F6 function key
+ { UCHAR_MAMEKEY(F7), "F7", NULL }, // F7 function key
+ { UCHAR_MAMEKEY(F8), "F8", NULL }, // F8 function key
+ { UCHAR_MAMEKEY(F9), "F9", NULL }, // F9 function key
+ { UCHAR_MAMEKEY(F10), "F10", NULL }, // F10 function key
+ { UCHAR_MAMEKEY(F11), "F11", NULL }, // F11 function key
+ { UCHAR_MAMEKEY(F12), "F12", NULL }, // F12 function key
+ { UCHAR_MAMEKEY(F13), "F13", NULL }, // F13 function key
+ { UCHAR_MAMEKEY(F14), "F14", NULL }, // F14 function key
+ { UCHAR_MAMEKEY(F15), "F15", NULL }, // F15 function key
+ { UCHAR_MAMEKEY(ESC), "Esc", "\033" }, // Esc key
+ { UCHAR_MAMEKEY(INSERT), "Insert", NULL }, // Insert key
+ { UCHAR_MAMEKEY(DEL), "Delete", "\010" }, // Delete key
+ { UCHAR_MAMEKEY(HOME), "Home", "\014" }, // Home key
+ { UCHAR_MAMEKEY(END), "End", NULL }, // End key
+ { UCHAR_MAMEKEY(PGUP), "Page Up", NULL }, // Page Up key
+ { UCHAR_MAMEKEY(PGDN), "Page Down", NULL }, // Page Down key
+ { UCHAR_MAMEKEY(LEFT), "Cursor Left", NULL }, // Cursor Left
+ { UCHAR_MAMEKEY(RIGHT), "Cursor Right", NULL }, // Cursor Right
+ { UCHAR_MAMEKEY(UP), "Cursor Up", NULL }, // Cursor Up
+ { UCHAR_MAMEKEY(DOWN), "Cursor Down", NULL }, // Cursor Down
+ { UCHAR_MAMEKEY(0_PAD), "Keypad 0", NULL }, // 0 on the numeric keypad
+ { UCHAR_MAMEKEY(1_PAD), "Keypad 1", NULL }, // 1 on the numeric keypad
+ { UCHAR_MAMEKEY(2_PAD), "Keypad 2", NULL }, // 2 on the numeric keypad
+ { UCHAR_MAMEKEY(3_PAD), "Keypad 3", NULL }, // 3 on the numeric keypad
+ { UCHAR_MAMEKEY(4_PAD), "Keypad 4", NULL }, // 4 on the numeric keypad
+ { UCHAR_MAMEKEY(5_PAD), "Keypad 5", NULL }, // 5 on the numeric keypad
+ { UCHAR_MAMEKEY(6_PAD), "Keypad 6", NULL }, // 6 on the numeric keypad
+ { UCHAR_MAMEKEY(7_PAD), "Keypad 7", NULL }, // 7 on the numeric keypad
+ { UCHAR_MAMEKEY(8_PAD), "Keypad 8", NULL }, // 8 on the numeric keypad
+ { UCHAR_MAMEKEY(9_PAD), "Keypad 9", NULL }, // 9 on the numeric keypad
+ { UCHAR_MAMEKEY(SLASH_PAD), "Keypad /", NULL }, // / on the numeric keypad
+ { UCHAR_MAMEKEY(ASTERISK), "Keypad *", NULL }, // * on the numeric keypad
+ { UCHAR_MAMEKEY(MINUS_PAD), "Keypad -", NULL }, // - on the numeric Keypad
+ { UCHAR_MAMEKEY(PLUS_PAD), "Keypad +", NULL }, // + on the numeric Keypad
+ { UCHAR_MAMEKEY(DEL_PAD), "Keypad .", NULL }, // . on the numeric keypad
+ { UCHAR_MAMEKEY(ENTER_PAD), "Keypad Enter", NULL }, // Enter on the numeric keypad
+ { UCHAR_MAMEKEY(PRTSCR), "Print Screen", NULL }, // Print Screen key
+ { UCHAR_MAMEKEY(PAUSE), "Pause", NULL }, // Pause key
+ { UCHAR_MAMEKEY(LSHIFT), "Left Shift", NULL }, // Left Shift key
+ { UCHAR_MAMEKEY(RSHIFT), "Right Shift", NULL }, // Right Shift key
+ { UCHAR_MAMEKEY(LCONTROL), "Left Ctrl", NULL }, // Left Control key
+ { UCHAR_MAMEKEY(RCONTROL), "Right Ctrl", NULL }, // Right Control key
+ { UCHAR_MAMEKEY(LALT), "Left Alt", NULL }, // Left Alt key
+ { UCHAR_MAMEKEY(RALT), "Right Alt", NULL }, // Right Alt key
+ { UCHAR_MAMEKEY(SCRLOCK), "Scroll Lock", NULL }, // Scroll Lock key
+ { UCHAR_MAMEKEY(NUMLOCK), "Num Lock", NULL }, // Num Lock key
+ { UCHAR_MAMEKEY(CAPSLOCK), "Caps Lock", NULL }, // Caps Lock key
+ { UCHAR_MAMEKEY(LWIN), "Left Win", NULL }, // Left Win key
+ { UCHAR_MAMEKEY(RWIN), "Right Win", NULL }, // Right Win key
+ { UCHAR_MAMEKEY(MENU), "Menu", NULL }, // Menu key
+ { UCHAR_MAMEKEY(CANCEL), "Break", NULL } // Break/Pause key
};
-static TIMER_CALLBACK(inputx_timerproc);
-/* Debugging commands and handlers. */
-static void execute_input(running_machine &machine, int ref, int params, const char *param[]);
-static void execute_dumpkbd(running_machine &machine, int ref, int params, const char *param[]);
-
-/***************************************************************************
- COMMON SHARED STRINGS
-***************************************************************************/
+//**************************************************************************
+// COMMON SHARED STRINGS
+//**************************************************************************
static const struct
{
@@ -686,2526 +782,2331 @@ static const struct
-/***************************************************************************
- BUILT-IN CORE MAPPINGS
-***************************************************************************/
+//**************************************************************************
+// BUILT-IN CORE MAPPINGS
+//**************************************************************************
#include "inpttype.h"
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
-
-/* core system management */
-static void input_port_exit(running_machine &machine);
-
-/* port reading */
-static INT32 apply_analog_settings(INT32 current, analog_field_state *analog);
-
-/* initialization helpers */
-static void init_port_types(running_machine &machine);
-static void init_port_state(running_machine &machine);
-static void init_autoselect_devices(running_machine &machine, int type1, int type2, int type3, const char *option, const char *ananame);
-static device_field_info *init_field_device_info(const input_field_config *field,const char *device_name);
-static analog_field_state *init_field_analog_state(const input_field_config *field);
-
-/* once-per-frame updates */
-static void frame_update_callback(running_machine &machine);
-static void frame_update(running_machine &machine);
-static void frame_update_digital_joysticks(running_machine &machine);
-static void frame_update_analog_field(running_machine &machine, analog_field_state *analog);
-static int frame_get_digital_field_state(const input_field_config *field, int mouse_down);
-
-/* tokenization helpers */
-static int token_to_input_field_type(running_machine &machine, const char *string, int *player);
-static const char *input_field_type_to_token(running_machine &machine, int type, int player);
-static int token_to_seq_type(const char *string);
-
-/* settings load */
-static void load_config_callback(running_machine &machine, int config_type, xml_data_node *parentnode);
-static void load_remap_table(running_machine &machine, xml_data_node *parentnode);
-static int load_default_config(running_machine &machine, xml_data_node *portnode, int type, int player, const input_seq *newseq);
-static int load_game_config(running_machine &machine, xml_data_node *portnode, int type, int player, const input_seq *newseq);
-
-/* settings save */
-static void save_config_callback(running_machine &machine, int config_type, xml_data_node *parentnode);
-static void save_sequence(running_machine &machine, xml_data_node *parentnode, int type, int porttype, const input_seq &seq);
-static int save_this_input_field_type(int type);
-static void save_default_inputs(running_machine &machine, xml_data_node *parentnode);
-static void save_game_inputs(running_machine &machine, xml_data_node *parentnode);
-
-/* input playback */
-static time_t playback_init(running_machine &machine);
-static void playback_end(running_machine &machine, const char *message);
-static void playback_frame(running_machine &machine, attotime curtime);
-static void playback_port(const input_port_config *port);
-
-/* input recording */
-static void record_init(running_machine &machine);
-static void record_end(running_machine &machine, const char *message);
-static void record_frame(running_machine &machine, attotime curtime);
-static void record_port(const input_port_config *port);
+//**************************************************************************
+// PORT CONFIGURATIONS
+//**************************************************************************
+//**************************************************************************
+// I/O PORT LIST
+//**************************************************************************
+//-------------------------------------------------
+// append - append the given device's input ports
+// to the current list
+//-------------------------------------------------
-/***************************************************************************
- INLINE FUNCTIONS
-***************************************************************************/
-
-/*-------------------------------------------------
- apply_analog_min_max - clamp the given input
- value to the appropriate min/max for the
- analog control
--------------------------------------------------*/
-
-INLINE INT32 apply_analog_min_max(const analog_field_state *analog, INT32 value)
+void ioport_list::append(device_t &device, astring &errorbuf)
{
- /* take the analog minimum and maximum values and apply the inverse of the */
- /* sensitivity so that we can clamp against them before applying sensitivity */
- INT32 adjmin = APPLY_INVERSE_SENSITIVITY(analog->minimum, analog->sensitivity);
- INT32 adjmax = APPLY_INVERSE_SENSITIVITY(analog->maximum, analog->sensitivity);
+ // no constructor, no list
+ ioport_constructor constructor = device.input_ports();
+ if (constructor == NULL)
+ return;
- /* for absolute devices, clamp to the bounds absolutely */
- if (!analog->wraps)
- {
- if (value > adjmax)
- value = adjmax;
- else if (value < adjmin)
- value = adjmin;
- }
+ // reset error buffer
+ errorbuf.reset();
- /* for relative devices, wrap around when we go past the edge */
- else
- {
- INT32 range = adjmax - adjmin;
- /* rolls to other end when 1 position past end. */
- value = (value - adjmin) % range;
- if (value < 0)
- value += range;
- value += adjmin;
- }
+ // detokenize into the list
+ (*constructor)(device, *this, errorbuf);
- return value;
+ // collapse fields and sort the list
+ for (ioport_port *port = first(); port != NULL; port = port->next())
+ port->collapse_fields(errorbuf);
}
-/*-------------------------------------------------
- get_port_tag - return a guaranteed tag for
- a port
--------------------------------------------------*/
-
-INLINE const char *get_port_tag(const input_port_config *port, char *tempbuffer)
-{
- return port->tag();
-}
+//**************************************************************************
+// INPUT TYPE ENTRY
+//**************************************************************************
-/*-------------------------------------------------
- condition_equal - TRUE if two conditions are
- equivalent
--------------------------------------------------*/
+//-------------------------------------------------
+// input_type_entry - constructors
+//-------------------------------------------------
-INLINE int condition_equal(const input_condition *cond1, const input_condition *cond2)
+input_type_entry::input_type_entry(ioport_type type, ioport_group group, int player, const char *token, const char *name, input_seq standard)
+ : m_next(NULL),
+ m_type(type),
+ m_group(group),
+ m_player(player),
+ m_token(token),
+ m_name(name)
{
- return (cond1->mask == cond2->mask && cond1->value == cond2->value && cond1->condition == cond2->condition && strcmp(cond1->tag, cond2->tag) == 0);
-}
-
-
-
-/***************************************************************************
- CORE SYSTEM MANAGEMENT
-***************************************************************************/
-
-/*-------------------------------------------------
- input_port_init - initialize the input port
- system
--------------------------------------------------*/
-
-ioport_manager::ioport_manager(running_machine &machine)
- : safe_to_read(false),
- last_frame_time(attotime::zero),
- last_delta_nsec(0),
- record_file(NULL),
- playback_file(NULL),
- playback_accumulated_speed(0),
- playback_accumulated_frames(0),
- codes(NULL),
- inputx_timer(NULL),
- queue_chars(NULL),
- accept_char(NULL),
- charqueue_empty(NULL),
- current_rate(attotime::zero),
- m_machine(machine)
-{
- memset(type_to_entry, 0, sizeof(type_to_entry));
- memset(joystick_info, 0, sizeof(joystick_info));
+ m_defseq[SEQ_TYPE_STANDARD] = m_seq[SEQ_TYPE_STANDARD] = standard;
}
-time_t ioport_manager::initialize()
+input_type_entry::input_type_entry(ioport_type type, ioport_group group, int player, const char *token, const char *name, input_seq standard, input_seq decrement, input_seq increment)
+ : m_next(NULL),
+ m_type(type),
+ m_group(group),
+ m_player(player),
+ m_token(token),
+ m_name(name)
{
- /* add an exit callback and a frame callback */
- machine().add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(input_port_exit), &machine()));
- machine().add_notifier(MACHINE_NOTIFY_FRAME, machine_notify_delegate(FUNC(frame_update_callback), &machine()));
-
- /* initialize the default port info from the OSD */
- init_port_types(machine());
-
- /* if we have a token list, proceed */
- device_iterator iter(machine().root_device());
- for (device_t *device = iter.first(); device != NULL; device = iter.next())
- {
- astring errors;
- input_port_list_init(*device, m_portlist, errors);
- if (errors)
- mame_printf_error("Input port errors:\n%s", errors.cstr());
- }
-
- init_port_state(machine());
- /* register callbacks for when we load configurations */
- config_register(machine(), "input", config_saveload_delegate(FUNC(load_config_callback), &machine()), config_saveload_delegate(FUNC(save_config_callback), &machine()));
-
- /* open playback and record files if specified */
- time_t basetime = playback_init(machine());
- record_init(machine());
-
- return basetime;
+ m_defseq[SEQ_TYPE_STANDARD] = m_seq[SEQ_TYPE_STANDARD] = standard;
+ m_defseq[SEQ_TYPE_INCREMENT] = m_seq[SEQ_TYPE_INCREMENT] = increment;
+ m_defseq[SEQ_TYPE_DECREMENT] = m_seq[SEQ_TYPE_DECREMENT] = decrement;
}
-/*-------------------------------------------------
- input_port_exit - exit callback to ensure
- we clean up and close our files
--------------------------------------------------*/
+//-------------------------------------------------
+// configure_osd - set the token and name of an
+// OSD entry
+//-------------------------------------------------
-static void input_port_exit(running_machine &machine)
+void input_type_entry::configure_osd(const char *token, const char *name)
{
- /* close any playback or recording files */
- playback_end(machine, NULL);
- record_end(machine, NULL);
+ assert(m_type >= IPT_OSD_1 && m_type <= IPT_OSD_16);
+ m_token = token;
+ m_name = name;
}
+//**************************************************************************
+// DIGITAL JOYSTICKS
+//**************************************************************************
-/***************************************************************************
- PORT CONFIGURATIONS
-***************************************************************************/
-
-/*-------------------------------------------------
- input_port_list_init - initialize an input
- port list structure and allocate ports
- according to the given tokens
--------------------------------------------------*/
+//-------------------------------------------------
+// digital_joystick - constructor
+//-------------------------------------------------
-void input_port_list_init(device_t &device, ioport_list &portlist, astring &errorbuf)
+digital_joystick::digital_joystick(int player, int number)
+ : m_player(player),
+ m_number(number),
+ m_current(0),
+ m_current4way(0),
+ m_previous(0)
{
- /* no constructor, no list */
- ioport_constructor constructor = device.input_ports();
- if (constructor == NULL)
- return;
+ memset(m_field, 0, sizeof(m_field));
+}
- /* reset error buffer */
- errorbuf.reset();
- /* detokenize into the list */
- (*constructor)(device, portlist, errorbuf);
+//-------------------------------------------------
+// set_axis - configure a single axis of a
+// digital joystick
+//-------------------------------------------------
- // collapse fields and sort the list
- for (input_port_config *port = portlist.first(); port != NULL; port = port->next())
- port->collapse_fields(errorbuf);
+digital_joystick::direction_t digital_joystick::set_axis(ioport_field &field)
+{
+ direction_t direction = direction_t((field.type() - (IPT_DIGITAL_JOYSTICK_FIRST + 1)) % 4);
+ m_field[direction] = &field;
+ return direction;
}
-/*-------------------------------------------------
- input_field_by_tag_and_mask - return a pointer
- to the first field that intersects the given
- mask on the tagged port
--------------------------------------------------*/
+//-------------------------------------------------
+// frame_update - update the state of digital
+// joysticks prior to accumulating the results
+// in a port
+//-------------------------------------------------
-const input_field_config *input_field_by_tag_and_mask(running_machine &machine, const char *tag, input_port_value mask)
+void digital_joystick::frame_update()
{
- const input_port_config *port = machine.root_device().ioport(tag);
+ // remember previous state and reset current state
+ m_previous = m_current;
+ m_current = 0;
- /* if we got the port, look for the field */
- if (port != NULL)
- for (const input_field_config *field = port->first_field(); field != NULL; field = field->next())
- if ((field->mask & mask) != 0)
- return field;
+ // read all the associated ports
+ running_machine *machine = NULL;
+ for (direction_t direction = JOYDIR_UP; direction < JOYDIR_COUNT; direction++)
+ if (m_field[direction] != NULL)
+ {
+ machine = &m_field[direction]->machine();
+ if (machine->input().seq_pressed(m_field[direction]->seq(SEQ_TYPE_STANDARD)))
+ m_current |= 1 << direction;
+ }
- return NULL;
+ // lock out opposing directions (left + right or up + down)
+ if ((m_current & (UP_BIT | DOWN_BIT)) == (UP_BIT | DOWN_BIT))
+ m_current &= ~(UP_BIT | DOWN_BIT);
+ if ((m_current & (LEFT_BIT | RIGHT_BIT)) == (LEFT_BIT | RIGHT_BIT))
+ m_current &= ~(LEFT_BIT | RIGHT_BIT);
+
+ // only update 4-way case if joystick has moved
+ if (m_current != m_previous)
+ {
+ m_current4way = m_current;
+
+ //
+ // If joystick is pointing at a diagonal, acknowledge that the player moved
+ // the joystick by favoring a direction change. This minimizes frustration
+ // when using a keyboard for input, and maximizes responsiveness.
+ //
+ // For example, if you are holding "left" then switch to "up" (where both left
+ // and up are briefly pressed at the same time), we'll transition immediately
+ // to "up."
+ //
+ // Zero any switches that didn't change from the previous to current state.
+ //
+ if ((m_current4way & (UP_BIT | DOWN_BIT)) &&
+ (m_current4way & (LEFT_BIT | RIGHT_BIT)))
+ {
+ m_current4way ^= m_current4way & m_previous;
+ }
+
+ //
+ // If we are still pointing at a diagonal, we are in an indeterminant state.
+ //
+ // This could happen if the player moved the joystick from the idle position directly
+ // to a diagonal, or from one diagonal directly to an extreme diagonal.
+ //
+ // The chances of this happening with a keyboard are slim, but we still need to
+ // constrain this case.
+ //
+ // For now, just resolve randomly.
+ //
+ if ((m_current4way & (UP_BIT | DOWN_BIT)) &&
+ (m_current4way & (LEFT_BIT | RIGHT_BIT)))
+ {
+ if (machine->rand() & 1)
+ m_current4way &= ~(LEFT_BIT | RIGHT_BIT);
+ else
+ m_current4way &= ~(UP_BIT | DOWN_BIT);
+ }
+ }
}
-/***************************************************************************
- ACCESSORS FOR INPUT FIELDS
-***************************************************************************/
+//**************************************************************************
+// NATURAL KEYBOARD
+//**************************************************************************
-/*-------------------------------------------------
- input_field_name - return the field name for
- a given input field
--------------------------------------------------*/
+//-------------------------------------------------
+// natural_keyboard - constructor
+//-------------------------------------------------
-const char *input_field_name(const input_field_config *field)
+natural_keyboard::natural_keyboard(running_machine &machine)
+ : m_machine(machine),
+ m_bufbegin(0),
+ m_bufend(0),
+ m_status_keydown(false),
+ m_last_cr(false),
+ m_timer(NULL),
+ m_current_rate(attotime::zero)
{
- /* if we have a non-default name, use that */
- if ((field->state != NULL) && (field->state->name != NULL))
- return field->state->name;
- if (field->name != NULL)
- return field->name;
+ // reigster debugger commands
+ if (machine.debug_flags & DEBUG_FLAG_ENABLED)
+ {
+ debug_console_register_command(machine, "input", CMDFLAG_NONE, 0, 1, 1, execute_input);
+ debug_console_register_command(machine, "dumpkbd", CMDFLAG_NONE, 0, 0, 1, execute_dumpkbd);
+ }
- /* otherwise, return the name associated with the type */
- return input_type_name(field->machine(), field->type, field->player);
+ // posting keys directly only makes sense for a computer
+ if (machine.ioport().has_keyboard())
+ {
+ m_buffer.resize(KEY_BUFFER_SIZE);
+ m_timer = machine.scheduler().timer_alloc(timer_expired_delegate(FUNC(natural_keyboard::timer), this));
+ build_codes(machine.ioport());
+ }
}
-/*-------------------------------------------------
- input_field_seq - return the input sequence
- for the given input field
--------------------------------------------------*/
+//-------------------------------------------------
+// configure - configure callbacks for full-
+// featured keyboard support
+//-------------------------------------------------
-const input_seq &input_field_seq(const input_field_config *field, input_seq_type seqtype)
+void natural_keyboard::configure(ioport_queue_chars_delegate queue_chars, ioport_accept_char_delegate accept_char, ioport_charqueue_empty_delegate charqueue_empty)
{
- /* if the field is disabled, return no key */
- if (field->flags & FIELD_FLAG_UNUSED)
- return input_seq::empty_seq;
-
- /* select either the live or config state depending on whether we have live state */
- const input_seq &portseq = (field->state == NULL) ? field->seq[seqtype] : field->state->seq[seqtype];
-
- /* if the portseq is the special default code, return the expanded default value */
- if (portseq.is_default())
- return input_type_seq(field->machine(), field->type, field->player, seqtype);
-
- /* otherwise, return the sequence as-is */
- return portseq;
+ // set the callbacks
+ m_queue_chars = queue_chars;
+ m_accept_char = accept_char;
+ m_charqueue_empty = charqueue_empty;
}
-/*-------------------------------------------------
- input_field_get_user_settings - return the current
- settings for the given input field
--------------------------------------------------*/
+//-------------------------------------------------
+// post - post a single character
+//-------------------------------------------------
-void input_field_get_user_settings(const input_field_config *field, input_field_user_settings *settings)
+void natural_keyboard::post(unicode_char ch)
{
- int seqtype;
-
- /* zap the entire structure */
- memset(settings, 0, sizeof(*settings));
-
- /* copy the basics */
- for (seqtype = 0; seqtype < ARRAY_LENGTH(settings->seq); seqtype++)
- settings->seq[seqtype] = field->state->seq[seqtype];
-
- /* if there's a list of settings or we're an adjuster, copy the current value */
- if (field->settinglist().count() != 0 || field->type == IPT_ADJUSTER)
- settings->value = field->state->value;
-
- /* if there's analog data, extract the analog settings */
- if (field->state->analog != NULL)
+ // ignore any \n that are preceded by \r
+ if (m_last_cr && ch == '\n')
{
- settings->sensitivity = field->state->analog->sensitivity;
- settings->delta = field->state->analog->delta;
- settings->centerdelta = field->state->analog->centerdelta;
- settings->reverse = field->state->analog->reverse;
+ m_last_cr = false;
+ return;
}
-}
+ // change all eolns to '\r'
+ if (ch == '\n')
+ ch = '\r';
+ else
+ m_last_cr = (ch == '\r');
-/*-------------------------------------------------
- input_field_set_user_settings - modify the current
- settings for the given input field
--------------------------------------------------*/
-
-void input_field_set_user_settings(const input_field_config *field, const input_field_user_settings *settings)
-{
- int seqtype;
-
- /* copy the basics */
- for (seqtype = 0; seqtype < ARRAY_LENGTH(settings->seq); seqtype++)
+ // logging
+ if (LOG_NATURAL_KEYBOARD)
{
- const input_seq &defseq = input_type_seq(field->machine(), field->type, field->player, (input_seq_type)seqtype);
- if (defseq == settings->seq[seqtype])
- field->state->seq[seqtype].set_default();
- else
- field->state->seq[seqtype] = settings->seq[seqtype];
+ const keycode_map_entry *code = find_code(ch);
+ astring tempstr;
+ logerror("natural_keyboard::post(): code=%i (%s) field->name='%s'\n", int(ch), unicode_to_string(tempstr, ch), (code != NULL && code->field[0] != NULL) ? code->field[0]->name() : "<null>");
}
- /* if there's a list of settings or we're an adjuster, copy the current value */
- if (field->settinglist().count() != 0 || field->type == IPT_ADJUSTER)
- field->state->value = settings->value;
+ // can we post this key in the queue directly?
+ if (can_post_directly(ch))
+ internal_post(ch);
- /* if there's analog data, extract the analog settings */
- if (field->state->analog != NULL)
+ // can we post this key with an alternate representation?
+ else if (can_post_alternate(ch))
{
- field->state->analog->sensitivity = settings->sensitivity;
- field->state->analog->delta = settings->delta;
- field->state->analog->centerdelta = settings->centerdelta;
- field->state->analog->reverse = settings->reverse;
+ const char_info *info = char_info::find(ch);
+ assert(info != NULL && info->alternate != NULL);
+ const char *altstring = info->alternate;
+ while (*altstring != 0)
+ {
+ altstring += uchar_from_utf8(&ch, altstring, strlen(altstring));
+ internal_post(ch);
+ }
}
}
-/*-------------------------------------------------
- input_field_setting_name - return the expanded
- setting name for a field
--------------------------------------------------*/
+//-------------------------------------------------
+// post - post a unicode encoded string
+//-------------------------------------------------
-const char *input_field_setting_name(const input_field_config *field)
+void natural_keyboard::post(const unicode_char *text, size_t length, attotime rate)
{
- const input_setting_config *setting;
-
- /* only makes sense if we have settings */
- assert(field->settinglist().count() != 0);
+ // set the fixed rate
+ m_current_rate = rate;
+
+ // 0 length means strlen
+ if (length == 0)
+ for (const unicode_char *scan = text; *scan != 0; scan++)
+ length++;
- /* scan the list of settings looking for a match on the current value */
- for (setting = field->settinglist().first(); setting != NULL; setting = setting->next())
- if (input_condition_true(field->machine(), &setting->condition, field->port().owner()))
- if (setting->value == field->state->value)
- return setting->name;
-
- return "INVALID";
+ // iterate over characters or until the buffer is full up
+ while (length > 0 && !full())
+ {
+ // fetch next character
+ post(*text++);
+ length--;
+ }
}
-/*-------------------------------------------------
- input_field_has_previous_setting - return TRUE
- if the given field has a "previous" setting
--------------------------------------------------*/
+//-------------------------------------------------
+// post_utf8 - post a UTF-8 encoded string
+//-------------------------------------------------
-int input_field_has_previous_setting(const input_field_config *field)
+void natural_keyboard::post_utf8(const char *text, size_t length, attotime rate)
{
- const input_setting_config *setting;
-
- /* only makes sense if we have settings */
- assert(field->settinglist().count() != 0);
-
- /* scan the list of settings looking for a match on the current value */
- for (setting = field->settinglist().first(); setting != NULL; setting = setting->next())
- if (input_condition_true(field->machine(), &setting->condition, field->port().owner()))
- return (setting->value != field->state->value);
+ // set the fixed rate
+ m_current_rate = rate;
+
+ // 0-length means strlen
+ if (length == 0)
+ length = strlen(text);
- return FALSE;
+ // iterate until out of characters
+ while (length > 0)
+ {
+ // decode the next character
+ unicode_char uc;
+ int count = uchar_from_utf8(&uc, text, length);
+ if (count < 0)
+ {
+ count = 1;
+ uc = INVALID_CHAR;
+ }
+
+ // append to the buffer
+ post(uc);
+ text += count;
+ length -= count;
+ }
}
-/*-------------------------------------------------
- input_field_select_previous_setting - select
- the previous item for a DIP switch or
- configuration field
--------------------------------------------------*/
+//-------------------------------------------------
+// post_coded - post a coded string
+//-------------------------------------------------
-void input_field_select_previous_setting(const input_field_config *field)
+void natural_keyboard::post_coded(const char *text, size_t length, attotime rate)
{
- const input_setting_config *setting, *prevsetting;
- int found_match = FALSE;
+ static const struct
+ {
+ const char *key;
+ unicode_char code;
+ } codes[] =
+ {
+ { "BACKSPACE", 8 },
+ { "BS", 8 },
+ { "BKSP", 8 },
+ { "DEL", UCHAR_MAMEKEY(DEL) },
+ { "DELETE", UCHAR_MAMEKEY(DEL) },
+ { "END", UCHAR_MAMEKEY(END) },
+ { "ENTER", 13 },
+ { "ESC", '\033' },
+ { "HOME", UCHAR_MAMEKEY(HOME) },
+ { "INS", UCHAR_MAMEKEY(INSERT) },
+ { "INSERT", UCHAR_MAMEKEY(INSERT) },
+ { "PGDN", UCHAR_MAMEKEY(PGDN) },
+ { "PGUP", UCHAR_MAMEKEY(PGUP) },
+ { "SPACE", 32 },
+ { "TAB", 9 },
+ { "F1", UCHAR_MAMEKEY(F1) },
+ { "F2", UCHAR_MAMEKEY(F2) },
+ { "F3", UCHAR_MAMEKEY(F3) },
+ { "F4", UCHAR_MAMEKEY(F4) },
+ { "F5", UCHAR_MAMEKEY(F5) },
+ { "F6", UCHAR_MAMEKEY(F6) },
+ { "F7", UCHAR_MAMEKEY(F7) },
+ { "F8", UCHAR_MAMEKEY(F8) },
+ { "F9", UCHAR_MAMEKEY(F9) },
+ { "F10", UCHAR_MAMEKEY(F10) },
+ { "F11", UCHAR_MAMEKEY(F11) },
+ { "F12", UCHAR_MAMEKEY(F12) },
+ { "QUOTE", '\"' }
+ };
- /* only makes sense if we have settings */
- assert(field->settinglist().count() != 0);
+ // set the fixed rate
+ m_current_rate = rate;
+
+ // 0-length means strlen
+ if (length == 0)
+ length = strlen(text);
- /* scan the list of settings looking for a match on the current value */
- prevsetting = NULL;
- for (setting = field->settinglist().first(); setting != NULL; setting = setting->next())
- if (input_condition_true(field->machine(), &setting->condition, field->port().owner()))
- {
- if (setting->value == field->state->value)
+ // iterate through the source string
+ size_t curpos = 0;
+ while (curpos < length)
+ {
+ // extract next character
+ unicode_char ch = text[curpos];
+ size_t increment = 1;
+
+ // look for escape characters
+ if (ch == '{')
+ for (int codenum = 0; codenum < ARRAY_LENGTH(codes); codenum++)
{
- found_match = TRUE;
- if (prevsetting != NULL)
- break;
+ size_t keylen = strlen(codes[codenum].key);
+ if (curpos + keylen + 2 <= length)
+ if (core_strnicmp(codes[codenum].key, &text[curpos + 1], keylen) == 0 && text[curpos + keylen + 1] == '}')
+ {
+ ch = codes[codenum].code;
+ increment = keylen + 2;
+ }
}
- prevsetting = setting;
- }
- /* if we didn't find a matching value, select the first */
- if (!found_match)
- {
- for (prevsetting = field->settinglist().first(); prevsetting != NULL; prevsetting = prevsetting->next())
- if (input_condition_true(field->machine(), &prevsetting->condition, field->port().owner()))
- break;
+ // if we got a code, post it
+ if (ch != 0)
+ post(ch);
+ curpos += increment;
}
-
- /* update the value to the previous one */
- if (prevsetting != NULL)
- field->state->value = prevsetting->value;
}
-/*-------------------------------------------------
- input_field_has_next_setting - return TRUE
- if the given field has a "next" setting
--------------------------------------------------*/
+//-------------------------------------------------
+// build_codes - given an input port table, create
+// an input code table useful for mapping unicode
+// chars
+//-------------------------------------------------
-int input_field_has_next_setting(const input_field_config *field)
+void natural_keyboard::build_codes(ioport_manager &manager)
{
- const input_setting_config *setting;
- int found = FALSE;
+ // iterate over shift keys
+ ioport_field *shift[UCHAR_SHIFT_END + 1 - UCHAR_SHIFT_BEGIN] = { 0 };
+ for (int curshift = 0; curshift <= ARRAY_LENGTH(shift); curshift++)
+ if (curshift == 0 || shift[curshift - 1] != NULL)
- /* only makes sense if we have settings */
- assert(field->settinglist().count() != 0);
+ // iterate over ports and fields
+ for (ioport_port *port = manager.first_port(); port != NULL; port = port->next())
+ for (ioport_field *field = port->first_field(); field != NULL; field = field->next())
+ if (field->type() == IPT_KEYBOARD)
+ {
+ // fetch the code, ignoring 0
+ unicode_char code = field->keyboard_code(curshift);
+ if (code == 0)
+ continue;
- /* scan the list of settings looking for a match on the current value */
- for (setting = field->settinglist().first(); setting != NULL; setting = setting->next())
- if (input_condition_true(field->machine(), &setting->condition, field->port().owner()))
- {
- if (found)
- return TRUE;
- if (setting->value == field->state->value)
- found = TRUE;
- }
+ // is this a shifter key?
+ if (code >= UCHAR_SHIFT_BEGIN && code <= UCHAR_SHIFT_END)
+ shift[code - UCHAR_SHIFT_BEGIN] = field;
- return FALSE;
+ // not a shifter key; record normally
+ else
+ {
+ keycode_map_entry newcode;
+ if (curshift == 0)
+ newcode.field[0] = field;
+ else
+ {
+ newcode.field[0] = shift[curshift - 1];
+ newcode.field[1] = field;
+ }
+ newcode.ch = code;
+ m_keycode_map.append(newcode);
+
+ if (LOG_NATURAL_KEYBOARD)
+ {
+ astring tempstr;
+ logerror("natural_keyboard: code=%i (%s) port=%p field->name='%s'\n", int(code), unicode_to_string(tempstr, code), port, field->name());
+ }
+ }
+ }
}
-/*-------------------------------------------------
- input_field_select_next_setting - select the
- next item for a DIP switch or
- configuration field
--------------------------------------------------*/
+//-------------------------------------------------
+// can_post_directly - determine if the given
+// unicode character can be directly posted
+//-------------------------------------------------
-void input_field_select_next_setting(const input_field_config *field)
+bool natural_keyboard::can_post_directly(unicode_char ch)
{
- const input_setting_config *setting, *nextsetting;
+ // if we have a queueing callback, then it depends on whether we can accept the character
+ if (!m_queue_chars.isnull())
+ return m_accept_char.isnull() ? true : m_accept_char(ch);
- /* only makes sense if we have settings */
- assert(field->settinglist().count() != 0);
+ // otherwise, it depends on the input codes
+ const keycode_map_entry *code = find_code(ch);
+ return (code != NULL && code->field[0] != NULL);
+}
- /* scan the list of settings looking for a match on the current value */
- nextsetting = NULL;
- for (setting = field->settinglist().first(); setting != NULL; setting = setting->next())
- if (input_condition_true(field->machine(), &setting->condition, field->port().owner()))
- if (setting->value == field->state->value)
- break;
- /* if we found one, scan forward for the next valid one */
- if (setting != NULL)
- for (nextsetting = setting->next(); nextsetting != NULL; nextsetting = nextsetting->next())
- if (input_condition_true(field->machine(), &nextsetting->condition, field->port().owner()))
- break;
+//-------------------------------------------------
+// can_post_alternate - determine if the given
+// unicode character can be posted via translation
+//-------------------------------------------------
- /* if we hit the end, search from the beginning */
- if (nextsetting == NULL)
- for (nextsetting = field->settinglist().first(); nextsetting != NULL; nextsetting = nextsetting->next())
- if (input_condition_true(field->machine(), &nextsetting->condition, field->port().owner()))
- break;
+bool natural_keyboard::can_post_alternate(unicode_char ch)
+{
+ const char_info *info = char_info::find(ch);
+ if (info == NULL)
+ return false;
+
+ const char *altstring = info->alternate;
+ if (altstring == NULL)
+ return false;
- /* update the value to the previous one */
- if (nextsetting != NULL)
- field->state->value = nextsetting->value;
+ while (*altstring != 0)
+ {
+ unicode_char uchar;
+ int count = uchar_from_utf8(&uchar, altstring, strlen(altstring));
+ if (count <= 0)
+ return false;
+ if (!can_post_directly(uchar))
+ return false;
+ altstring += count;
+ }
+ return true;
}
+//-------------------------------------------------
+// choose_delay - determine the delay between
+// posting keyboard events
+//-------------------------------------------------
-/***************************************************************************
- ACCESSORS FOR INPUT TYPES
-***************************************************************************/
+attotime natural_keyboard::choose_delay(unicode_char ch)
+{
+ // if we have a live rate, just use that
+ if (m_current_rate != attotime::zero)
+ return m_current_rate;
-/*-------------------------------------------------
- input_type_is_analog - return TRUE if
- the given type represents an analog control
--------------------------------------------------*/
+ // systems with queue_chars can afford a much smaller delay
+ if (!m_queue_chars.isnull())
+ return attotime::from_msec(10);
-int input_type_is_analog(int type)
-{
- return (type >= __ipt_analog_start && type <= __ipt_analog_end);
+ // otherwise, default to constant delay with a longer delay on CR
+ return attotime::from_msec((ch == '\r') ? 200 : 50);
}
-/*-------------------------------------------------
- input_type_name - return the name
- for the given type/player
--------------------------------------------------*/
+//-------------------------------------------------
+// internal_post - post a keyboard event
+//-------------------------------------------------
-const char *input_type_name(running_machine &machine, int type, int player)
+void natural_keyboard::internal_post(unicode_char ch)
{
- /* if we have a machine, use the live state and quick lookup */
- ioport_manager &portdata = machine.ioport();
- input_type_entry *entry = portdata.type_to_entry[type][player];
- if (entry != NULL)
- return entry->name;
+ // need to start up the timer?
+ if (empty())
+ {
+ m_timer->adjust(choose_delay(ch));
+ m_status_keydown = 0;
+ }
- /* if we find nothing, return an invalid group */
- return "???";
+ // add to the buffer, resizing if necessary
+ m_buffer[m_bufend++] = ch;
+ if ((m_bufend + 1) % m_buffer.count() == m_bufbegin)
+ m_buffer.resize(m_buffer.count() + KEY_BUFFER_SIZE, true);
+ m_bufend %= m_buffer.count();
}
-/*-------------------------------------------------
- input_type_group - return the group
- for the given type/player
--------------------------------------------------*/
+//-------------------------------------------------
+// timer - timer callback to keep things flowing
+// when posting a string of characters
+//-------------------------------------------------
-int input_type_group(running_machine &machine, int type, int player)
+void natural_keyboard::timer(void *ptr, int param)
{
- ioport_manager &portdata = machine.ioport();
- input_type_entry *entry = portdata.type_to_entry[type][player];
- if (entry != NULL)
- return entry->group;
+ // the driver has a queue_chars handler
+ if (!m_queue_chars.isnull())
+ {
+ while (!empty() && m_queue_chars(&m_buffer[m_bufbegin], 1))
+ {
+ m_bufbegin = (m_bufbegin + 1) % m_buffer.count();
+ if (m_current_rate != attotime::zero)
+ break;
+ }
+ }
- /* if we find nothing, return an invalid group */
- return IPG_INVALID;
+ // the driver does not have a queue_chars handler
+ else
+ {
+ if (m_status_keydown)
+ m_bufbegin = (m_bufbegin + 1) % m_buffer.count();
+ m_status_keydown = !m_status_keydown;
+ }
+
+ // need to make sure timerproc is called again if buffer not empty
+ if (!empty())
+ m_timer->adjust(choose_delay(m_buffer[m_bufbegin]));
}
-/*-------------------------------------------------
- input_type_seq - return the input
- sequence for the given type/player
--------------------------------------------------*/
+//-------------------------------------------------
+// unicode_to_string - obtain a string
+// representation of a given code; used for
+// logging and debugging
+//-------------------------------------------------
-const input_seq &input_type_seq(running_machine &machine, int type, int player, input_seq_type seqtype)
+const char *natural_keyboard::unicode_to_string(astring &buffer, unicode_char ch)
{
- assert(type >= 0 && type < __ipt_max);
- assert(player >= 0 && player < MAX_PLAYERS);
+ buffer.reset();
+ switch (ch)
+ {
+ // check some magic values
+ case '\0': buffer.cpy("\\0"); break;
+ case '\r': buffer.cpy("\\r"); break;
+ case '\n': buffer.cpy("\\n"); break;
+ case '\t': buffer.cpy("\\t"); break;
- /* if we have a machine, use the live state and quick lookup */
- ioport_manager &portdata = machine.ioport();
- input_type_entry *entry = portdata.type_to_entry[type][player];
- if (entry != NULL)
- return entry->seq[seqtype];
+ default:
+ // seven bit ASCII is easy
+ if (ch >= 32 && ch < 128)
+ {
+ char temp[2] = { char(ch), 0 };
+ buffer.cpy(temp);
+ }
+ else if (ch >= UCHAR_MAMEKEY_BEGIN)
+ {
+ // try to obtain a codename with code_name(); this can result in an empty string
+ input_code code(DEVICE_CLASS_KEYBOARD, 0, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, input_item_id(ch - UCHAR_MAMEKEY_BEGIN));
+ machine().input().code_name(buffer, code);
+ }
- /* if we find nothing, return an empty sequence */
- return input_seq::empty_seq;
+ // did we fail to resolve? if so, we have a last resort
+ if (buffer.len() == 0)
+ buffer.format("U+%04X", unsigned(ch));
+ break;
+ }
+ return buffer;
}
-/*-------------------------------------------------
- input_type_set_seq - change the input
- sequence for the given type/player
--------------------------------------------------*/
+//-------------------------------------------------
+// find_code - find a code in our lookup table
+//-------------------------------------------------
-void input_type_set_seq(running_machine &machine, int type, int player, input_seq_type seqtype, const input_seq *newseq)
+const natural_keyboard::keycode_map_entry *natural_keyboard::find_code(unicode_char ch) const
{
- ioport_manager &portdata = machine.ioport();
- input_type_entry *entry = portdata.type_to_entry[type][player];
- if (entry != NULL)
- entry->seq[seqtype] = *newseq;
+ for (int code = 0; m_keycode_map[code].ch != 0; code++)
+ if (m_keycode_map[code].ch == ch)
+ return &m_keycode_map[code];
+ return NULL;
}
-/*-------------------------------------------------
- input_type_pressed - return TRUE if
- the sequence for the given input type/player
- is pressed
--------------------------------------------------*/
+//-------------------------------------------------
+// frame_update - once per frame update of the
+// natural keyboard state
+//-------------------------------------------------
-int input_type_pressed(running_machine &machine, int type, int player)
+void natural_keyboard::frame_update(ioport_port &port, ioport_value &digital)
{
- return machine.input().seq_pressed(input_type_seq(machine, type, player, SEQ_TYPE_STANDARD));
+ // is there currently a key down?
+ if (m_status_keydown && !empty())
+ {
+ // loop through this character's component codes
+ const keycode_map_entry *code = find_code(m_buffer[m_bufbegin]);
+ if (code != NULL)
+ for (int fieldnum = 0; fieldnum < ARRAY_LENGTH(code->field) && code->field[fieldnum] != NULL; fieldnum++)
+ if (&code->field[fieldnum]->port() == &port)
+ digital |= code->field[fieldnum]->mask();
+ }
}
-/*-------------------------------------------------
- input_type_list - return the list of types
--------------------------------------------------*/
+//-------------------------------------------------
+// key_name - returns the name of a specific key
+//-------------------------------------------------
-const simple_list<input_type_entry> &input_type_list(running_machine &machine)
+const char *natural_keyboard::key_name(astring &string, unicode_char ch)
{
- ioport_manager &portdata = machine.ioport();
- return portdata.typelist;
-}
-
+ // attempt to get the string from the character info table
+ const char_info *ci = char_info::find(ch);
+ const char *result = (ci != NULL) ? ci->name : NULL;
+ if (result != NULL)
+ string.cpy(result);
+ // if that doesn't work, convert to UTF-8
+ else if (ch > 0x7F || isprint(ch))
+ {
+ char buf[10];
+ int count = utf8_from_uchar(buf, ARRAY_LENGTH(buf), ch);
+ buf[count] = 0;
+ string.cpy(buf);
+ }
-/***************************************************************************
- PORT CHECKING
-***************************************************************************/
-
-
-/*-------------------------------------------------
- input_port_exists - return whether an input
- port exists
--------------------------------------------------*/
-
-bool input_port_exists(running_machine &machine, const char *tag)
-{
- return machine.root_device().ioport(tag) != 0;
+ // otherwise, opt for question marks
+ else
+ string.cpy("???");
+ return string;
}
-/*-------------------------------------------------
- input_port_active - return a bitmask of which
- bits of an input port are active (i.e. not
- unused or unknown)
--------------------------------------------------*/
+//-------------------------------------------------
+// execute_input - debugger command to enter
+// natural keyboard input
+//-------------------------------------------------
-input_port_value input_port_active(running_machine &machine, const char *tag)
+void natural_keyboard::execute_input(running_machine &machine, int ref, int params, const char *param[])
{
- const input_port_config *port = machine.root_device().ioport(tag);
- if (port == NULL)
- fatalerror("Unable to locate input port '%s'", tag);
- return port->active;
+ machine.ioport().natkeyboard().post_coded(param[0]);
}
-/*-------------------------------------------------
- input_port_active_safe - return a bitmask of
- which bits of an input port are active (i.e.
- not unused or unknown), or a default value if
- the port does not exist
--------------------------------------------------*/
+//-------------------------------------------------
+// execute_dumpkbd - debugger command to natural
+// keyboard codes
+//-------------------------------------------------
-input_port_value input_port_active_safe(running_machine &machine, const char *tag, input_port_value defvalue)
+void natural_keyboard::execute_dumpkbd(running_machine &machine, int ref, int params, const char *param[])
{
- const input_port_config *port = machine.root_device().ioport(tag);
- return port == NULL ? defvalue : port->active;
-}
+ // was there a file specified?
+ const char *filename = (params > 0) ? param[0] : NULL;
+ FILE *file = NULL;
+ if (filename != NULL)
+ {
+ // if so, open it
+ file = fopen(filename, "w");
+ if (file == NULL)
+ {
+ debug_console_printf(machine, "Cannot open \"%s\"\n", filename);
+ return;
+ }
+ }
+
+ // loop through all codes
+ natural_keyboard &natkeyboard = machine.ioport().natkeyboard();
+ dynamic_array<keycode_map_entry> &keycode_map = natkeyboard.m_keycode_map;
+ astring buffer, tempstr;
+ const size_t left_column_width = 24;
+ for (int index = 0; index < keycode_map.count(); index++)
+ {
+ // describe the character code
+ const keycode_map_entry &code = keycode_map[index];
+ buffer.printf("%08X (%s) ", code.ch, natkeyboard.unicode_to_string(tempstr, code.ch));
+ // pad with spaces
+ while (buffer.len() < left_column_width)
+ buffer.cat(' ');
+ // identify the keys used
+ for (int field = 0; field < ARRAY_LENGTH(code.field) && code.field[field] != 0; field++)
+ buffer.catprintf("%s'%s'", (field > 0) ? ", " : "", code.field[field]->name());
-/***************************************************************************
- PORT READING
-***************************************************************************/
+ // and output it as appropriate
+ if (file != NULL)
+ fprintf(file, "%s\n", buffer.cstr());
+ else
+ debug_console_printf(machine, "%s\n", buffer.cstr());
+ }
-/*-------------------------------------------------
- input_port_read_direct - return the value of
- an input port
--------------------------------------------------*/
+ // cleanup
+ if (file != NULL)
+ fclose(file);
+}
-input_port_value input_port_read_direct(const input_port_config *port)
-{
- assert(port != NULL);
- ioport_manager &portdata = port->machine().ioport();
- analog_field_state *analog;
- device_field_info *device_field;
- input_port_value result;
- assert_always(portdata.safe_to_read, "Input ports cannot be read at init time!");
+//**************************************************************************
+// I/O PORT CONDITION
+//**************************************************************************
- /* start with the digital */
- result = port->state->digital;
+//-------------------------------------------------
+// eval - evaluate condition
+//-------------------------------------------------
- /* update read values */
- for (device_field = port->state->readdevicelist; device_field != NULL; device_field = device_field->next)
- if (input_condition_true(port->machine(), &device_field->field->condition, port->owner()))
- {
- /* replace the bits with bits from the device */
- input_port_value newval = device_field->field->read(*device_field->field, device_field->field->read_param);
- device_field->oldval = newval;
- result = (result & ~device_field->field->mask) | ((newval << device_field->shift) & device_field->field->mask);
- }
+bool ioport_condition::eval(device_t &device) const
+{
+ // always condition is always true
+ if (m_condition == ALWAYS)
+ return true;
- /* update VBLANK bits */
- if (port->state->vblank != 0)
+ // otherwise, read the referenced port and switch off the condition type
+ ioport_value condvalue = device.ioport(m_tag)->read();
+ switch (m_condition)
{
- if (port->machine().primary_screen->vblank())
- result |= port->state->vblank;
- else
- result &= ~port->state->vblank;
+ case ALWAYS: return true;
+ case EQUALS: return ((condvalue & m_mask) == m_value);
+ case NOTEQUALS: return ((condvalue & m_mask) != m_value);
+ case GREATERTHAN: return ((condvalue & m_mask) > m_value);
+ case NOTGREATERTHAN: return ((condvalue & m_mask) <= m_value);
+ case LESSTHAN: return ((condvalue & m_mask) < m_value);
+ case NOTLESSTHAN: return ((condvalue & m_mask) >= m_value);
}
+ return true;
+}
- /* apply active high/low state to digital, read, and VBLANK inputs */
- result ^= port->state->defvalue;
-
- /* merge in analog portions */
- for (analog = port->state->analoglist; analog != NULL; analog = analog->next)
- if (input_condition_true(port->machine(), &analog->field->condition, port->owner()))
- {
- /* start with the raw value */
- INT32 value = analog->accum;
- /* interpolate if appropriate and if time has passed since the last update */
- if (analog->interpolate && !(analog->field->flags & ANALOG_FLAG_RESET) && portdata.last_delta_nsec != 0)
- {
- attoseconds_t nsec_since_last = (port->machine().time() - portdata.last_frame_time).as_attoseconds() / ATTOSECONDS_PER_NANOSECOND;
- value = analog->previous + ((INT64)(analog->accum - analog->previous) * nsec_since_last / portdata.last_delta_nsec);
- }
- /* apply standard analog settings */
- value = apply_analog_settings(value, analog);
+//**************************************************************************
+// I/O PORT SETTING
+//**************************************************************************
- /* remap the value if needed */
- if (analog->field->remap_table != NULL)
- value = analog->field->remap_table[value];
+//-------------------------------------------------
+// ioport_setting - constructor
+//-------------------------------------------------
- /* invert bits if needed */
- if (analog->field->flags & ANALOG_FLAG_INVERT)
- value = ~value;
+ioport_setting::ioport_setting(ioport_field &field, ioport_value _value, const char *_name)
+ : m_next(NULL),
+ m_field(field),
+ m_value(_value),
+ m_name(_name)
+{
+}
- /* insert into the port */
- result = (result & ~analog->field->mask) | ((value << analog->shift) & analog->field->mask);
- }
- return result;
-}
+//**************************************************************************
+// I/O PORT DIP LOCATION
+//**************************************************************************
-/*-------------------------------------------------
- input_port_read - return the value of
- an input port specified by tag
--------------------------------------------------*/
+//-------------------------------------------------
+// ioport_diplocation - constructor
+//-------------------------------------------------
-input_port_value input_port_read(running_machine &machine, const char *tag)
+ioport_diplocation::ioport_diplocation(const char *name, UINT8 swnum, bool invert)
+ : m_next(NULL),
+ m_name(name),
+ m_number(swnum),
+ m_invert(invert)
{
- const input_port_config *port = machine.root_device().ioport(tag);
- if (port == NULL)
- fatalerror("Unable to locate input port '%s'", tag);
- return input_port_read_direct(port);
}
-/*-------------------------------------------------
- input_port_read - return the value of
- a device input port specified by tag
--------------------------------------------------*/
-input_port_value input_port_read(device_t &device, const char *tag)
-{
- const input_port_config *port = device.ioport(tag);
- if (port == NULL)
- fatalerror("Unable to locate input port '%s'", tag);
- return input_port_read_direct(port);
+//**************************************************************************
+// I/O PORT FIELD
+//**************************************************************************
+
+//-------------------------------------------------
+// ioport_field - constructor
+//-------------------------------------------------
+
+ioport_field::ioport_field(ioport_port &port, ioport_type type, ioport_value defvalue, ioport_value maskbits, const char *name)
+ : m_next(NULL),
+ m_port(port),
+ m_live(NULL),
+ m_modcount(port.modcount()),
+ m_mask(maskbits),
+ m_defvalue(defvalue & maskbits),
+ m_type(type),
+ m_player(0),
+ m_flags(0),
+ m_impulse(0),
+ m_name(name),
+ m_read_param(NULL),
+ m_write_param(NULL),
+ m_min(0),
+ m_max(maskbits),
+ m_sensitivity(0),
+ m_delta(0),
+ m_centerdelta(0),
+ m_crosshair_axis(CROSSHAIR_AXIS_NONE),
+ m_crosshair_scale(1.0),
+ m_crosshair_offset(0),
+ m_crosshair_altaxis(0),
+ m_full_turn_count(0),
+ m_remap_table(NULL),
+ m_way(0)
+{
+ // reset sequences and chars
+ for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++)
+ m_seq[seqtype].set_default();
+ m_chars[0] = m_chars[1] = m_chars[2] = unicode_char(0);
+
+ // for DIP switches and configs, look for a default value from the owner
+ if (type == IPT_DIPSWITCH || type == IPT_CONFIG)
+ {
+ const input_device_default *def = device().input_ports_defaults();
+ if (def != NULL)
+ {
+ const char *fulltag = port.tag();
+ astring fullpath;
+ for ( ; def->tag != NULL; def++)
+ if (device().subtag(fullpath, def->tag) == fulltag && def->mask == m_mask)
+ m_defvalue = def->defvalue & m_mask;
+ }
+ }
}
-/*-------------------------------------------------
- input_port_read_safe - return the value of
- an input port specified by tag, or a default
- value if the port does not exist
--------------------------------------------------*/
+//-------------------------------------------------
+// ~ioport_field - destructor
+//-------------------------------------------------
-input_port_value input_port_read_safe(running_machine &machine, const char *tag, UINT32 defvalue)
+ioport_field::~ioport_field()
{
- const input_port_config *port = machine.root_device().ioport(tag);
- return (port == NULL) ? defvalue : input_port_read_direct(port);
+ global_free(m_live);
}
-/*-------------------------------------------------
- input_port_read_crosshair - return the
- extracted crosshair values for the given
- player
--------------------------------------------------*/
+//-------------------------------------------------
+// name - return the field name for a given input
+// field
+//-------------------------------------------------
-int input_port_get_crosshair_position(running_machine &machine, int player, float *x, float *y)
+const char *ioport_field::name() const
{
- const input_port_config *port;
- const input_field_config *field;
- int gotx = FALSE, goty = FALSE;
+ // if we have a non-default name, use that
+ if (m_live != NULL && m_live->name)
+ return m_live->name;
+ if (m_name != NULL)
+ return m_name;
- /* read all the lightgun values */
- for (port = machine.ioport().first_port(); port != NULL; port = port->next())
- for (field = port->first_field(); field != NULL; field = field->next())
- if (field->player == player && field->crossaxis != CROSSHAIR_AXIS_NONE)
- if (input_condition_true(machine, &field->condition, port->owner()))
- {
- analog_field_state *analog = field->state->analog;
- INT32 rawvalue = apply_analog_settings(analog->accum, analog) & (analog->field->mask >> analog->shift);
- float value = (float)(rawvalue - field->state->analog->adjmin) / (float)(field->state->analog->adjmax - field->state->analog->adjmin);
+ // otherwise, return the name associated with the type
+ return machine().ioport().type_name(m_type, m_player);
+}
- /* apply the scale and offset */
- if (field->crossscale < 0)
- value = -(1.0 - value) * field->crossscale;
- else
- value *= field->crossscale;
- value += field->crossoffset;
- /* apply custom mapping if necessary */
- if (!field->crossmapper.isnull())
- value = field->crossmapper(*field, value);
+//-------------------------------------------------
+// seq - return the input sequence for the given
+// input field
+//-------------------------------------------------
- /* handle X axis */
- if (field->crossaxis == CROSSHAIR_AXIS_X)
- {
- *x = value;
- gotx = TRUE;
- if (field->crossaltaxis != 0)
- {
- *y = field->crossaltaxis;
- goty = TRUE;
- }
- }
+const input_seq &ioport_field::seq(input_seq_type seqtype) const
+{
+ // if the field is disabled, return no key
+ if (m_flags & FIELD_FLAG_UNUSED)
+ return input_seq::empty_seq;
- /* handle Y axis */
- else
- {
- *y = value;
- goty = TRUE;
- if (field->crossaltaxis != 0)
- {
- *x = field->crossaltaxis;
- gotx = TRUE;
- }
- }
+ // select either the live or config state depending on whether we have live state
+ const input_seq &portseq = (m_live == NULL) ? m_seq[seqtype] : m_live->seq[seqtype];
- /* if we got both, stop */
- if (gotx && goty)
- break;
- }
+ // if the portseq is the special default code, return the expanded default value
+ if (portseq.is_default())
+ return machine().ioport().type_seq(m_type, m_player, seqtype);
- return (gotx && goty);
+ // otherwise, return the sequence as-is
+ return portseq;
}
-/*-------------------------------------------------
- input_port_update_defaults - force an update
- to the input port values based on current
- conditions
--------------------------------------------------*/
+//-------------------------------------------------
+// type_class - return the type class for this
+// field
+//-------------------------------------------------
-void input_port_update_defaults(running_machine &machine)
+ioport_type_class ioport_field::type_class() const
{
- int loopnum;
+ ioport_type_class result;
- /* two passes to catch conditionals properly */
- for (loopnum = 0; loopnum < 2; loopnum++)
+ switch (m_type)
{
- const input_port_config *port;
+ case IPT_JOYSTICK_UP:
+ case IPT_JOYSTICK_DOWN:
+ case IPT_JOYSTICK_LEFT:
+ case IPT_JOYSTICK_RIGHT:
+ case IPT_JOYSTICKLEFT_UP:
+ case IPT_JOYSTICKLEFT_DOWN:
+ case IPT_JOYSTICKLEFT_LEFT:
+ case IPT_JOYSTICKLEFT_RIGHT:
+ case IPT_JOYSTICKRIGHT_UP:
+ case IPT_JOYSTICKRIGHT_DOWN:
+ case IPT_JOYSTICKRIGHT_LEFT:
+ case IPT_JOYSTICKRIGHT_RIGHT:
+ case IPT_BUTTON1:
+ case IPT_BUTTON2:
+ case IPT_BUTTON3:
+ case IPT_BUTTON4:
+ case IPT_BUTTON5:
+ case IPT_BUTTON6:
+ case IPT_BUTTON7:
+ case IPT_BUTTON8:
+ case IPT_BUTTON9:
+ case IPT_BUTTON10:
+ case IPT_AD_STICK_X:
+ case IPT_AD_STICK_Y:
+ case IPT_AD_STICK_Z:
+ case IPT_TRACKBALL_X:
+ case IPT_TRACKBALL_Y:
+ case IPT_LIGHTGUN_X:
+ case IPT_LIGHTGUN_Y:
+ case IPT_MOUSE_X:
+ case IPT_MOUSE_Y:
+ case IPT_START:
+ case IPT_SELECT:
+ result = INPUT_CLASS_CONTROLLER;
+ break;
- /* loop over all input ports */
- for (port = machine.ioport().first_port(); port != NULL; port = port->next())
- {
- const input_field_config *field;
+ case IPT_KEYPAD:
+ case IPT_KEYBOARD:
+ result = INPUT_CLASS_KEYBOARD;
+ break;
- /* only clear on the first pass */
- if (loopnum == 0)
- port->state->defvalue = 0;
+ case IPT_CONFIG:
+ result = INPUT_CLASS_CONFIG;
+ break;
- /* first compute the default value for the entire port */
- for (field = port->first_field(); field != NULL; field = field->next())
- if (input_condition_true(machine, &field->condition, port->owner()))
- port->state->defvalue = (port->state->defvalue & ~field->mask) | (field->state->value & field->mask);
- }
+ case IPT_DIPSWITCH:
+ result = INPUT_CLASS_DIPSWITCH;
+ break;
+
+ case 0:
+ if (m_name != NULL && m_name != (const char *)-1)
+ result = INPUT_CLASS_MISC;
+ else
+ result = INPUT_CLASS_INTERNAL;
+ break;
+
+ default:
+ result = INPUT_CLASS_INTERNAL;
+ break;
}
+ return result;
}
-/*-------------------------------------------------
- apply_analog_settings - return the value of
- an input port
--------------------------------------------------*/
+//-------------------------------------------------
+// keyboard_code - accesses a particular keyboard
+// code
+//-------------------------------------------------
-static INT32 apply_analog_settings(INT32 value, analog_field_state *analog)
+unicode_char ioport_field::keyboard_code(int which) const
{
- /* apply the min/max and then the sensitivity */
- value = apply_analog_min_max(analog, value);
- value = APPLY_SENSITIVITY(value, analog->sensitivity);
+ unicode_char ch = m_chars[which];
- /* apply reversal if needed */
- if (analog->reverse)
- value = analog->reverse_val - value;
- else if (analog->single_scale)
- /* it's a pedal or the default value is equal to min/max */
- /* so we need to adjust the center to the minimum */
- value -= INPUT_ABSOLUTE_MIN;
-
- /* map differently for positive and negative values */
- if (value >= 0)
- value = APPLY_SCALE(value, analog->scalepos);
- else
- value = APPLY_SCALE(value, analog->scaleneg);
- value += analog->adjdefvalue;
-
- return value;
+ // special hack to allow for PORT_CODE('\xA3')
+ if (ch >= 0xffffff80 && ch <= 0xffffffff)
+ ch &= 0xff;
+ return ch;
}
-/***************************************************************************
- PORT WRITING
-***************************************************************************/
-
-/*-------------------------------------------------
- input_port_write_direct - write a value
- to a port
--------------------------------------------------*/
+//-------------------------------------------------
+// get_user_settings - return the current
+// settings for the given input field
+//-------------------------------------------------
-void input_port_write_direct(const input_port_config *port, input_port_value data, input_port_value mem_mask)
+void ioport_field::get_user_settings(user_settings &settings)
{
- /* call device line write handlers */
- device_field_info *device_field;
+ // zap the entire structure
+ memset(&settings, 0, sizeof(settings));
- COMBINE_DATA(&port->state->outputvalue);
+ // copy the basics
+ for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++)
+ settings.seq[seqtype] = m_live->seq[seqtype];
- for (device_field = port->state->writedevicelist; device_field; device_field = device_field->next)
- if (device_field->field->type == IPT_OUTPUT && input_condition_true(port->machine(), &device_field->field->condition, port->owner()))
- {
- input_port_value newval = ( (port->state->outputvalue ^ device_field->field->defvalue ) & device_field->field->mask) >> device_field->shift;
-
- /* if the bits have write, call the handler */
- if (device_field->oldval != newval)
- {
- device_field->field->write(*device_field->field, device_field->field->write_param, device_field->oldval, newval);
+ // if there's a list of settings or we're an adjuster, copy the current value
+ if (first_setting() != NULL || m_type == IPT_ADJUSTER)
+ settings.value = m_live->value;
- device_field->oldval = newval;
- }
- }
+ // if there's analog data, extract the analog settings
+ if (m_live->analog != NULL)
+ {
+ settings.sensitivity = m_live->analog->sensitivity();
+ settings.delta = m_live->analog->delta();
+ settings.centerdelta = m_live->analog->centerdelta();
+ settings.reverse = m_live->analog->reverse();
+ }
}
-/*-------------------------------------------------
- input_port_write - write a value to a
- port specified by tag
--------------------------------------------------*/
+//-------------------------------------------------
+// set_user_settings - modify the current
+// settings for the given input field
+//-------------------------------------------------
-void input_port_write(running_machine &machine, const char *tag, input_port_value value, input_port_value mask)
+void ioport_field::set_user_settings(const user_settings &settings)
{
- const input_port_config *port = machine.root_device().ioport(tag);
- if (port == NULL)
- fatalerror("Unable to locate input port '%s'", tag);
- input_port_write_direct(port, value, mask);
-}
-
+ // copy the basics
+ for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++)
+ {
+ const input_seq &defseq = manager().type_seq(m_type, m_player, input_seq_type(seqtype));
+ if (defseq == settings.seq[seqtype])
+ m_live->seq[seqtype].set_default();
+ else
+ m_live->seq[seqtype] = settings.seq[seqtype];
+ }
-/*-------------------------------------------------
- input_port_write_safe - write a value to
- a port, ignore if the port does not exist
--------------------------------------------------*/
+ // if there's a list of settings or we're an adjuster, copy the current value
+ if (first_setting() != NULL || m_type == IPT_ADJUSTER)
+ m_live->value = settings.value;
-void input_port_write_safe(running_machine &machine, const char *tag, input_port_value value, input_port_value mask)
-{
- const input_port_config *port = machine.root_device().ioport(tag);
- if (port != NULL)
- input_port_write_direct(port, value, mask);
+ // if there's analog data, extract the analog settings
+ if (m_live->analog != NULL)
+ {
+ m_live->analog->m_sensitivity = settings.sensitivity;
+ m_live->analog->m_delta = settings.delta;
+ m_live->analog->m_centerdelta = settings.centerdelta;
+ m_live->analog->m_reverse = settings.reverse;
+ }
}
+//-------------------------------------------------
+// setting_name - return the expanded setting
+// name for a field
+//-------------------------------------------------
-/***************************************************************************
- MISC HELPER FUNCTIONS
-***************************************************************************/
-
-/*-------------------------------------------------
- input_condition_true - return the TRUE
- if the given condition attached is true
--------------------------------------------------*/
-
-int input_condition_true(running_machine &machine, const input_condition *condition, device_t &owner)
+const char *ioport_field::setting_name() const
{
- input_port_value condvalue;
-
- /* always condition is always true */
- if (condition->condition == PORTCOND_ALWAYS)
- return TRUE;
+ // only makes sense if we have settings
+ assert(first_setting() != NULL);
- /* otherwise, read the referenced port */
- astring conditiontag;
- owner.subtag(conditiontag, condition->tag);
- condvalue = input_port_read(machine, conditiontag.cstr());
+ // scan the list of settings looking for a match on the current value
+ for (ioport_setting *setting = first_setting(); setting != NULL; setting = setting->next())
+ if (setting->enabled())
+ if (setting->value() == m_live->value)
+ return setting->name();
- /* based on the condition encoded, determine truth */
- switch (condition->condition)
- {
- case PORTCOND_EQUALS:
- return ((condvalue & condition->mask) == condition->value);
+ return "INVALID";
+}
- case PORTCOND_NOTEQUALS:
- return ((condvalue & condition->mask) != condition->value);
- case PORTCOND_GREATERTHAN:
- return ((condvalue & condition->mask) > condition->value);
+//-------------------------------------------------
+// has_previous_setting - return true if the
+// given field has a "previous" setting
+//-------------------------------------------------
- case PORTCOND_NOTGREATERTHAN:
- return ((condvalue & condition->mask) <= condition->value);
+bool ioport_field::has_previous_setting() const
+{
+ // only makes sense if we have settings
+ assert(first_setting() != NULL);
- case PORTCOND_LESSTHAN:
- return ((condvalue & condition->mask) < condition->value);
+ // scan the list of settings looking for a match on the current value
+ for (ioport_setting *setting = first_setting(); setting != NULL; setting = setting->next())
+ if (setting->enabled())
+ return (setting->value() != m_live->value);
- case PORTCOND_NOTLESSTHAN:
- return ((condvalue & condition->mask) >= condition->value);
- }
- return TRUE;
+ return false;
}
-/*-------------------------------------------------
- input_port_string_from_token - convert an
- input_port_token to a default string
--------------------------------------------------*/
+//-------------------------------------------------
+// select_previous_setting - select the previous
+// item for a DIP switch or configuration field
+//-------------------------------------------------
-const char *input_port_string_from_token(const char *string)
+void ioport_field::select_previous_setting()
{
- /* 0 is an invalid index */
- if (string == NULL)
- return NULL;
-
- /* if the index is greater than the count, assume it to be a pointer */
- if (FPTR(string) >= INPUT_STRING_COUNT)
- return string;
+ // only makes sense if we have settings
+ assert(first_setting() != NULL);
-#if FALSE // Set TRUE, If you want to take care missing-token or wrong-sorting
+ // scan the list of settings looking for a match on the current value
+ ioport_setting *prevsetting = NULL;
+ bool found_match = false;
+ for (ioport_setting *setting = first_setting(); setting != NULL; setting = setting->next())
+ if (setting->enabled())
+ {
+ if (setting->value() == m_live->value)
+ {
+ found_match = true;
+ if (prevsetting != NULL)
+ break;
+ }
+ prevsetting = setting;
+ }
- /* otherwise, scan the list for a matching string and return it */
+ // if we didn't find a matching value, select the first
+ if (!found_match)
{
- int index;
- for (index = 0; index < ARRAY_LENGTH(input_port_default_strings); index++)
- if (input_port_default_strings[index].id == FPTR(string))
- return input_port_default_strings[index].string;
+ for (prevsetting = first_setting(); prevsetting != NULL; prevsetting = prevsetting->next())
+ if (prevsetting->enabled())
+ break;
}
- return "(Unknown Default)";
-
-#else
-
- return input_port_default_strings[FPTR(string)-1].string;
-#endif
+ // update the value to the previous one
+ if (prevsetting != NULL)
+ m_live->value = prevsetting->value();
}
+//-------------------------------------------------
+// has_next_setting - return true if the given
+// field has a "next" setting
+//-------------------------------------------------
-/***************************************************************************
- INITIALIZATION HELPERS
-***************************************************************************/
-
-/*-------------------------------------------------
- init_port_types - initialize the default
- type list
--------------------------------------------------*/
-
-static void init_port_types(running_machine &machine)
+bool ioport_field::has_next_setting() const
{
- ioport_manager &portdata = machine.ioport();
+ // only makes sense if we have settings
+ assert(first_setting() != NULL);
- /* convert the array into a list of type states that can be modified */
- construct_core_types(portdata.typelist);
-
- /* ask the OSD to customize the list */
- machine.osd().customize_input_type_list(portdata.typelist);
-
- /* now iterate over the OSD-modified types */
- for (input_type_entry *curtype = portdata.typelist.first(); curtype != NULL; curtype = curtype->next())
- {
- /* first copy all the OSD-updated sequences into our current state */
- for (int seqtype = 0; seqtype < ARRAY_LENGTH(curtype->seq); seqtype++)
- curtype->seq[seqtype] = curtype->defseq[seqtype];
+ // scan the list of settings looking for a match on the current value
+ bool found = false;
+ for (ioport_setting *setting = first_setting(); setting != NULL; setting = setting->next())
+ if (setting->enabled())
+ {
+ if (found)
+ return true;
+ if (setting->value() == m_live->value)
+ found = true;
+ }
- /* also make a lookup table mapping type/player to the appropriate type list entry */
- portdata.type_to_entry[curtype->type][curtype->player] = curtype;
- }
+ return false;
}
-/*-------------------------------------------------
- get_keyboard_code - accesses a particular
- keyboard code
--------------------------------------------------*/
+//-------------------------------------------------
+// select_next_setting - select the next item for
+// a DIP switch or configuration field
+//-------------------------------------------------
-static unicode_char get_keyboard_code(const input_field_config *field, int i)
+void ioport_field::select_next_setting()
{
- unicode_char ch = field->chars[i];
+ // only makes sense if we have settings
+ assert(first_setting() != NULL);
- /* special hack to allow for PORT_CODE('\xA3') */
- if ((ch >= 0xFFFFFF80) && (ch <= 0xFFFFFFFF))
- ch &= 0xFF;
- return ch;
-}
+ // scan the list of settings looking for a match on the current value
+ ioport_setting *nextsetting = NULL;
+ ioport_setting *setting;
+ for (setting = first_setting(); setting != NULL; setting = setting->next())
+ if (setting->enabled())
+ if (setting->value() == m_live->value)
+ break;
+ // if we found one, scan forward for the next valid one
+ if (setting != NULL)
+ for (nextsetting = setting->next(); nextsetting != NULL; nextsetting = nextsetting->next())
+ if (nextsetting->enabled())
+ break;
-/***************************************************************************
- MISCELLANEOUS
-***************************************************************************/
+ // if we hit the end, search from the beginning
+ if (nextsetting == NULL)
+ for (nextsetting = first_setting(); nextsetting != NULL; nextsetting = nextsetting->next())
+ if (nextsetting->enabled())
+ break;
+
+ // update the value to the previous one
+ if (nextsetting != NULL)
+ m_live->value = nextsetting->value();
+}
-/*-------------------------------------------------
- find_charinfo - looks up information about a
- particular character
--------------------------------------------------*/
-static const char_info *find_charinfo(unicode_char target_char)
+//-------------------------------------------------
+// frame_update_digital - get the state of a
+// digital field
+//-------------------------------------------------
+
+void ioport_field::frame_update(ioport_value &result, bool mouse_down)
{
- int low = 0;
- int high = ARRAY_LENGTH(charinfo);
- int i;
- unicode_char ch;
+ // skip if not enabled
+ if (!enabled())
+ return;
- /* perform a simple binary search to find the proper alternate */
- while(high > low)
+ // handle analog inputs first
+ if (m_live->analog != NULL)
{
- i = (high + low) / 2;
- ch = charinfo[i].ch;
- if (ch < target_char)
- low = i + 1;
- else if (ch > target_char)
- high = i;
- else
- return &charinfo[i];
+ m_live->analog->frame_update(machine());
+ return;
}
- return NULL;
-}
-
-/*-------------------------------------------------
- inputx_key_name - returns the name of a
- specific key
--------------------------------------------------*/
+
+ // if UI is active, ignore digital inputs
+ if (ui_is_menu_active())
+ return;
-static const char *inputx_key_name(unicode_char ch)
-{
- static char buf[UTF8_CHAR_MAX + 1];
- const char_info *ci;
- const char *result;
- int pos;
+ // if the state changed, look for switch down/switch up
+ bool curstate = mouse_down || machine().input().seq_pressed(seq());
+ bool changed = false;
+ if (curstate != m_live->last)
+ {
+ m_live->last = curstate;
+ changed = true;
+ }
- ci = find_charinfo(ch);
- result = ci ? ci->name : NULL;
+ // if we're a keyboard type and using natural keyboard, bail
+ if (m_type == IPT_KEYBOARD && ui_get_use_natural_keyboard(machine()))
+ return;
- if (ci && ci->name)
+ // coin impulse option
+ int effective_impulse = m_impulse;
+ int impulse_option_val = machine().options().coin_impulse();
+ if (impulse_option_val != 0)
{
- result = ci->name;
+ if (impulse_option_val < 0)
+ effective_impulse = 0;
+ else if ((m_type >= IPT_COIN1 && m_type <= IPT_COIN12) || m_impulse != 0)
+ effective_impulse = impulse_option_val;
}
- else
+
+ // if this is a switch-down event, handle impulse and toggle
+ if (changed && curstate)
{
- if ((ch > 0x7F) || isprint(ch))
+ // impluse controls: reset the impulse counter
+ if (effective_impulse != 0 && m_live->impulse == 0)
+ m_live->impulse = effective_impulse;
+
+ // toggle controls: flip the toggle state or advance to the next setting
+ if (toggle())
{
- pos = utf8_from_uchar(buf, ARRAY_LENGTH(buf), ch);
- buf[pos] = '\0';
- result = buf;
+ if (m_settinglist.count() == 0)
+ m_live->value ^= m_mask;
+ else
+ select_next_setting();
}
- else
- result = "???";
}
- return result;
-}
-/*-------------------------------------------------
- get_keyboard_key_name - builds the name of
- a key based on natural keyboard characters
--------------------------------------------------*/
-
-static astring &get_keyboard_key_name(astring &name, const input_field_config *field)
-{
- int i;
- unicode_char ch;
-
- name.reset();
- /* loop through each character on the field*/
- for (i = 0; i < ARRAY_LENGTH(field->chars) && (field->chars[i] != '\0'); i++)
+ // update the current state with the impulse state
+ if (effective_impulse != 0)
{
- ch = get_keyboard_code(field, i);
- name.catprintf("%-*s ", MAX(SPACE_COUNT - 1, 0), inputx_key_name(ch));
+ curstate = (m_live->impulse != 0);
+ if (curstate)
+ m_live->impulse--;
}
- /* trim extra spaces */
- name.trimspace();
-
- /* special case */
- if (name.len() == 0)
- name.cpy("Unnamed Key");
-
- return name;
-}
-
-/*-------------------------------------------------
- init_port_state - initialize the live port
- states based on the tokens
--------------------------------------------------*/
+ // for toggle switches, the current value is folded into the port's default value
+ // so we always return FALSE here
+ if (toggle())
+ curstate = false;
-static void init_port_state(running_machine &machine)
-{
- const char *joystick_map_default = machine.options().joystick_map();
- ioport_manager &portdata = machine.ioport();
- input_field_config *field;
- input_port_config *port;
+ // additional logic to restrict digital joysticks
+ if (curstate && !mouse_down && m_live->joystick != NULL && m_way != 16 && !machine().options().joystick_contradictory())
+ {
+ UINT8 mask = (m_way == 4) ? m_live->joystick->current4way() : m_live->joystick->current();
+ if (!(mask & (1 << m_live->joydir)))
+ curstate = false;
+ }
- /* allocate live structures to mirror the configuration */
- for (port = machine.ioport().first_port(); port != NULL; port = port->next())
+ // skip locked-out coin inputs
+ if (curstate && m_type >= IPT_COIN1 && m_type <= IPT_COIN12 && coin_lockout_get_state(machine(), m_type - IPT_COIN1))
{
- analog_field_state **analogstatetail;
- device_field_info **readdevicetail;
- device_field_info **writedevicetail;
- input_port_state *portstate;
-
- /* allocate a new input_port_info structure */
- portstate = auto_alloc_clear(machine, input_port_state);
- ((input_port_config *)port)->state = portstate;
-
- /* start with tail pointers to all the data */
- analogstatetail = &portstate->analoglist;
- readdevicetail = &portstate->readdevicelist;
- writedevicetail = &portstate->writedevicelist;
-
- /* iterate over fields */
- for (field = port->first_field(); field != NULL; field = field->next())
+ bool verbose = machine().options().verbose();
+#ifdef MAME_DEBUG
+ verbose = true;
+#endif
+ if (machine().options().coin_lockout())
{
- input_field_state *fieldstate;
- int seqtype;
-
- /* allocate a new input_field_info structure */
- fieldstate = auto_alloc_clear(machine, input_field_state);
- ((input_field_config *)field)->state = fieldstate;
-
- /* fill in the basic values */
- for (seqtype = 0; seqtype < ARRAY_LENGTH(fieldstate->seq); seqtype++)
- fieldstate->seq[seqtype] = field->seq[seqtype];
- fieldstate->value = field->defvalue;
-
- /* if this is an analog field, allocate memory for the analog data */
- if (field->type >= __ipt_analog_start && field->type <= __ipt_analog_end)
- {
- *analogstatetail = fieldstate->analog = init_field_analog_state(field);
- analogstatetail = &(*analogstatetail)->next;
- }
-
- /* if this is a digital joystick field, make a note of it */
- if (field->type >= __ipt_digital_joystick_start && field->type <= __ipt_digital_joystick_end)
- {
- fieldstate->joystick = &portdata.joystick_info[field->player][(field->type - __ipt_digital_joystick_start) / 4];
- fieldstate->joydir = (field->type - __ipt_digital_joystick_start) % 4;
- fieldstate->joystick->field[fieldstate->joydir] = field;
- fieldstate->joystick->inuse = TRUE;
- }
-
- /* if this entry has device input, allocate memory for the tracking structure */
- astring devicetag;
- if (!field->read.isnull())
- {
- *readdevicetail = init_field_device_info(field, port->owner().subtag(devicetag, field->read_device));
- field->read.late_bind(*(*readdevicetail)->device);
- if (!field->read.has_object())
- fatalerror("Input port %s, unable to find valid device with tag '%s'", port->tag(), devicetag.cstr());
- readdevicetail = &(*readdevicetail)->next;
- }
-
- /* if this entry has device output, allocate memory for the tracking structure */
- if (!field->write.isnull())
- {
- *writedevicetail = init_field_device_info(field, port->owner().subtag(devicetag, field->write_device));
- field->write.late_bind(*(*writedevicetail)->device);
- if (!field->write.has_object())
- fatalerror("Input port %s, unable to find valid device with tag '%s'", port->tag(), devicetag.cstr());
- writedevicetail = &(*writedevicetail)->next;
- }
-
- /* if this entry has device output, allocate memory for the tracking structure */
- if (!field->crossmapper.isnull())
- {
- device_t *device = machine.device(port->owner().subtag(devicetag, field->crossmapper_device));
- field->crossmapper.late_bind(*device);
- }
-
- /* Name keyboard key names */
- if ((field->type == IPT_KEYBOARD || field->type == IPT_KEYPAD) && (field->name == NULL))
- {
- astring name;
- field->state->name = auto_strdup(machine, get_keyboard_key_name(name, field));
- }
+ if (verbose)
+ ui_popup_time(3, "Coinlock disabled %s.", name());
+ curstate = false;
}
+ else
+ if (verbose)
+ ui_popup_time(3, "Coinlock disabled, but broken through %s.", name());
}
- /* handle autoselection of devices */
- init_autoselect_devices(machine, IPT_AD_STICK_X, IPT_AD_STICK_Y, IPT_AD_STICK_Z, OPTION_ADSTICK_DEVICE, "analog joystick");
- init_autoselect_devices(machine, IPT_PADDLE, IPT_PADDLE_V, 0, OPTION_PADDLE_DEVICE, "paddle");
- init_autoselect_devices(machine, IPT_PEDAL, IPT_PEDAL2, IPT_PEDAL3, OPTION_PEDAL_DEVICE, "pedal");
- init_autoselect_devices(machine, IPT_LIGHTGUN_X, IPT_LIGHTGUN_Y, 0, OPTION_LIGHTGUN_DEVICE, "lightgun");
- init_autoselect_devices(machine, IPT_POSITIONAL, IPT_POSITIONAL_V, 0, OPTION_POSITIONAL_DEVICE, "positional");
- init_autoselect_devices(machine, IPT_DIAL, IPT_DIAL_V, 0, OPTION_DIAL_DEVICE, "dial");
- init_autoselect_devices(machine, IPT_TRACKBALL_X, IPT_TRACKBALL_Y, 0, OPTION_TRACKBALL_DEVICE, "trackball");
- init_autoselect_devices(machine, IPT_MOUSE_X, IPT_MOUSE_Y, 0, OPTION_MOUSE_DEVICE, "mouse");
-
- /* look for 4-way joysticks and change the default map if we find any */
- if (joystick_map_default[0] == 0 || strcmp(joystick_map_default, "auto") == 0)
- for (port = machine.ioport().first_port(); port != NULL; port = port->next())
- for (field = port->first_field(); field != NULL; field = field->next())
- if (field->state->joystick != NULL && field->way == 4)
- {
- machine.input().set_global_joystick_map((field->flags & FIELD_FLAG_ROTATED) ? joystick_map_4way_diagonal : joystick_map_4way_sticky);
- break;
- }
+ // if we're active, set the appropriate bits in the digital state
+ if (curstate)
+ result |= m_mask;
}
-/*-------------------------------------------------
- init_autoselect_devices - autoselect a single
- device based on the input port list passed
- in and the corresponding option
--------------------------------------------------*/
+//-------------------------------------------------
+// crosshair_position - compute the crosshair
+// position
+//-------------------------------------------------
-static void init_autoselect_devices(running_machine &machine, int type1, int type2, int type3, const char *option, const char *ananame)
+void ioport_field::crosshair_position(float &x, float &y, bool &gotx, bool &goty)
{
- const char *stemp = machine.options().value(option);
- input_device_class autoenable = DEVICE_CLASS_KEYBOARD;
- const char *autostring = "keyboard";
- const input_field_config *field;
- const input_port_config *port;
+ float value = m_live->analog->crosshair_read();
- /* if nothing specified, ignore the option */
- if (stemp[0] == 0)
- return;
+ // apply the scale and offset
+ if (m_crosshair_scale < 0)
+ value = -(1.0 - value) * m_crosshair_scale;
+ else
+ value *= m_crosshair_scale;
+ value += m_crosshair_offset;
- /* extract valid strings */
- if (strcmp(stemp, "mouse") == 0)
- {
- autoenable = DEVICE_CLASS_MOUSE;
- autostring = "mouse";
- }
- else if (strcmp(stemp, "joystick") == 0)
- {
- autoenable = DEVICE_CLASS_JOYSTICK;
- autostring = "joystick";
- }
- else if (strcmp(stemp, "lightgun") == 0)
+ // apply custom mapping if necessary
+ if (!m_crosshair_mapper.isnull())
+ value = m_crosshair_mapper(*this, value);
+
+ // handle X axis
+ if (m_crosshair_axis == CROSSHAIR_AXIS_X)
{
- autoenable = DEVICE_CLASS_LIGHTGUN;
- autostring = "lightgun";
+ x = value;
+ gotx = true;
+ if (m_crosshair_altaxis != 0)
+ {
+ y = m_crosshair_altaxis;
+ goty = true;
+ }
}
- else if (strcmp(stemp, "none") == 0)
+
+ // handle Y axis
+ else
{
- /* nothing specified */
- return;
+ y = value;
+ goty = true;
+ if (m_crosshair_altaxis != 0)
+ {
+ x = m_crosshair_altaxis;
+ gotx = true;
+ }
}
- else if (strcmp(stemp, "keyboard") != 0)
- mame_printf_error("Invalid %s value %s; reverting to keyboard\n", option, stemp);
-
- /* only scan the list if we haven't already enabled this class of control */
- if (machine.ioport().first_port() != NULL && !machine.input().device_class(autoenable).enabled())
- for (port = machine.ioport().first_port(); port != NULL; port = port->next())
- for (field = port->first_field(); field != NULL; field = field->next())
-
- /* if this port type is in use, apply the autoselect criteria */
- if ((type1 != 0 && field->type == type1) ||
- (type2 != 0 && field->type == type2) ||
- (type3 != 0 && field->type == type3))
- {
- mame_printf_verbose("Input: Autoenabling %s due to presence of a %s\n", autostring, ananame);
- machine.input().device_class(autoenable).enable();
- break;
- }
}
-/*-------------------------------------------------
- init_field_device_info - allocate and populate
- information about a device callback
--------------------------------------------------*/
+//-------------------------------------------------
+// expand_diplocation - expand a string-based
+// DIP location into a linked list of
+// descriptions
+//-------------------------------------------------
-static device_field_info *init_field_device_info(const input_field_config *field, const char *device_name)
+void ioport_field::expand_diplocation(const char *location, astring &errorbuf)
{
- device_field_info *info;
- input_port_value mask;
-
- /* allocate memory */
- info = auto_alloc_clear(field->machine(), device_field_info);
-
- /* fill in the data */
- info->field = field;
- for (mask = field->mask; !(mask & 1); mask >>= 1)
- info->shift++;
+ // if nothing present, bail
+ if (location == NULL)
+ return;
- info->device = (device_name != NULL) ? field->machine().device(device_name) : &field->port().owner();
+ m_diploclist.reset();
- info->oldval = field->defvalue >> info->shift;
- return info;
-}
+ // parse the string
+ astring name; // Don't move this variable inside the loop, lastname's lifetime depends on it being outside
+ const char *lastname = NULL;
+ const char *curentry = location;
+ int entries = 0;
+ while (*curentry != 0)
+ {
+ // find the end of this entry
+ const char *comma = strchr(curentry, ',');
+ if (comma == NULL)
+ comma = curentry + strlen(curentry);
+ // extract it to tempbuf
+ astring tempstr;
+ tempstr.cpy(curentry, comma - curentry);
-/*-------------------------------------------------
- init_field_analog_state - allocate and populate
- information about an analog port
--------------------------------------------------*/
+ // first extract the switch name if present
+ const char *number = tempstr;
+ const char *colon = strchr(tempstr, ':');
-static analog_field_state *init_field_analog_state(const input_field_config *field)
-{
- analog_field_state *state;
- input_port_value mask;
+ // allocate and copy the name if it is present
+ if (colon != NULL)
+ {
+ lastname = name.cpy(number, colon - number);
+ number = colon + 1;
+ }
- /* allocate memory */
- state = auto_alloc_clear(field->machine(), analog_field_state);
+ // otherwise, just copy the last name
+ else
+ {
+ if (lastname == NULL)
+ {
+ errorbuf.catprintf("Switch location '%s' missing switch name!\n", location);
+ lastname = (char *)"UNK";
+ }
+ name.cpy(lastname);
+ }
- /* compute the shift amount and number of bits */
- for (mask = field->mask; !(mask & 1); mask >>= 1)
- state->shift++;
+ // if the number is preceded by a '!' it's active high
+ bool invert = false;
+ if (*number == '!')
+ {
+ invert = true;
+ number++;
+ }
- /* initialize core data */
- state->field = field;
- state->adjdefvalue = (field->defvalue & field->mask) >> state->shift;
- state->adjmin = (field->min & field->mask) >> state->shift;
- state->adjmax = (field->max & field->mask) >> state->shift;
- state->sensitivity = field->sensitivity;
- state->reverse = ((field->flags & ANALOG_FLAG_REVERSE) != 0);
- state->delta = field->delta;
- state->centerdelta = field->centerdelta;
- state->minimum = INPUT_ABSOLUTE_MIN;
- state->maximum = INPUT_ABSOLUTE_MAX;
+ // now scan the switch number
+ int swnum = -1;
+ if (sscanf(number, "%d", &swnum) != 1)
+ errorbuf.catprintf("Switch location '%s' has invalid format!\n", location);
- /* set basic parameters based on the configured type */
- switch (field->type)
- {
- /* paddles and analog joysticks are absolute and autocenter */
- case IPT_AD_STICK_X:
- case IPT_AD_STICK_Y:
- case IPT_AD_STICK_Z:
- case IPT_PADDLE:
- case IPT_PADDLE_V:
- state->absolute = TRUE;
- state->autocenter = TRUE;
- state->interpolate = TRUE;
- break;
+ // allocate a new entry
+ m_diploclist.append(*global_alloc(ioport_diplocation(name, swnum, invert)));
+ entries++;
- /* pedals start at and autocenter to the min range */
- case IPT_PEDAL:
- case IPT_PEDAL2:
- case IPT_PEDAL3:
- state->center = INPUT_ABSOLUTE_MIN;
- state->accum = APPLY_INVERSE_SENSITIVITY(state->center, state->sensitivity);
- state->absolute = TRUE;
- state->autocenter = TRUE;
- state->interpolate = TRUE;
- break;
+ // advance to the next item
+ curentry = comma;
+ if (*curentry != 0)
+ curentry++;
+ }
- /* lightguns are absolute as well, but don't autocenter and don't interpolate their values */
- case IPT_LIGHTGUN_X:
- case IPT_LIGHTGUN_Y:
- state->absolute = TRUE;
- state->autocenter = FALSE;
- state->interpolate = FALSE;
- break;
+ // then verify the number of bits in the mask matches
+ ioport_value temp;
+ int bits;
+ for (bits = 0, temp = m_mask; temp != 0 && bits < 32; bits++)
+ temp &= temp - 1;
+ if (bits != entries)
+ errorbuf.catprintf("Switch location '%s' does not describe enough bits for mask %X\n", location, m_mask);
+}
- /* positional devices are absolute, but can also wrap like relative devices */
- /* set each position to be 512 units */
- case IPT_POSITIONAL:
- case IPT_POSITIONAL_V:
- state->positionalscale = COMPUTE_SCALE(field->max, INPUT_ABSOLUTE_MAX - INPUT_ABSOLUTE_MIN);
- state->adjmin = 0;
- state->adjmax = field->max - 1;
- state->wraps = ((field->flags & ANALOG_FLAG_WRAPS) != 0);
- state->autocenter = !state->wraps;
- break;
- /* dials, mice and trackballs are relative devices */
- /* these have fixed "min" and "max" values based on how many bits are in the port */
- /* in addition, we set the wrap around min/max values to 512 * the min/max values */
- /* this takes into account the mapping that one mouse unit ~= 512 analog units */
- case IPT_DIAL:
- case IPT_DIAL_V:
- case IPT_TRACKBALL_X:
- case IPT_TRACKBALL_Y:
- case IPT_MOUSE_X:
- case IPT_MOUSE_Y:
- state->absolute = FALSE;
- state->wraps = TRUE;
- state->interpolate = TRUE;
- break;
+//-------------------------------------------------
+// init_live_state - create live state structures
+//-------------------------------------------------
- default:
- fatalerror("Unknown analog port type -- don't know if it is absolute or not");
- break;
- }
+void ioport_field::init_live_state(analog_field *analog)
+{
+ // resolve callbacks
+ m_read.bind_relative_to(device());
+ m_write.bind_relative_to(device());
+ m_crosshair_mapper.bind_relative_to(device());
- /* further processing for absolute controls */
- if (state->absolute)
- {
- /* if the default value is pegged at the min or max, use a single scale value for the whole axis */
- state->single_scale = (state->adjdefvalue == state->adjmin) || (state->adjdefvalue == state->adjmax);
+ // allocate live state
+ m_live = global_alloc(ioport_field_live(*this, analog));
+}
- /* if not "single scale", compute separate scales for each side of the default */
- if (!state->single_scale)
- {
- /* unsigned */
- state->scalepos = COMPUTE_SCALE(state->adjmax - state->adjdefvalue, INPUT_ABSOLUTE_MAX - 0);
- state->scaleneg = COMPUTE_SCALE(state->adjdefvalue - state->adjmin, 0 - INPUT_ABSOLUTE_MIN);
- if (state->adjmin > state->adjmax)
- state->scaleneg = -state->scaleneg;
- /* reverse point is at center */
- state->reverse_val = 0;
- }
- else
- {
- /* single axis that increases from default */
- state->scalepos = COMPUTE_SCALE(state->adjmax - state->adjmin, INPUT_ABSOLUTE_MAX - INPUT_ABSOLUTE_MIN);
+//**************************************************************************
+// I/O PORT FIELD LIVE
+//**************************************************************************
- /* move from default */
- if (state->adjdefvalue == state->adjmax)
- state->scalepos = -state->scalepos;
+//-------------------------------------------------
+// ioport_field_live - constructor
+//-------------------------------------------------
- /* make the scaling the same for easier coding when we need to scale */
- state->scaleneg = state->scalepos;
+ioport_field_live::ioport_field_live(ioport_field &field, analog_field *analog)
+ : analog(analog),
+ joystick(NULL),
+ value(field.defvalue()),
+ impulse(0),
+ last(0),
+ joydir(digital_joystick::JOYDIR_COUNT)
+{
+ // fill in the basic values
+ for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++)
+ seq[seqtype] = field.seq(seqtype);
- /* reverse point is at max */
- state->reverse_val = state->maximum;
- }
+ // if this is a digital joystick field, make a note of it
+ if (field.is_digital_joystick())
+ {
+ joystick = &field.manager().digjoystick(field.player(), (field.type() - (IPT_DIGITAL_JOYSTICK_FIRST + 1)) / 4);
+ joydir = joystick->set_axis(field);
}
- /* relative and positional controls all map directly with a 512x scale factor */
- else
+ // Name keyboard key names
+ if (field.type_class() == INPUT_CLASS_KEYBOARD && field.specific_name() == NULL)
{
- /* The relative code is set up to allow specifing PORT_MINMAX and default values. */
- /* The validity checks are purposely set up to not allow you to use anything other */
- /* a default of 0 and PORT_MINMAX(0,mask). This is in case the need arises to use */
- /* this feature in the future. Keeping the code in does not hurt anything. */
- if (state->adjmin > state->adjmax)
- /* adjust for signed */
- state->adjmin = -state->adjmin;
-
- if (state->wraps)
- state->adjmax++;
-
- state->minimum = (state->adjmin - state->adjdefvalue) * INPUT_RELATIVE_PER_PIXEL;
- state->maximum = (state->adjmax - state->adjdefvalue) * INPUT_RELATIVE_PER_PIXEL;
-
- /* make the scaling the same for easier coding when we need to scale */
- state->scaleneg = state->scalepos = COMPUTE_SCALE(1, INPUT_RELATIVE_PER_PIXEL);
-
- if (field->flags & ANALOG_FLAG_RESET)
- /* delta values reverse from center */
- state->reverse_val = 0;
- else
+ // loop through each character on the field
+ astring tempstr;
+ for (int which = 0; ; which++)
{
- /* positional controls reverse from their max range */
- state->reverse_val = state->maximum + state->minimum;
-
- /* relative controls reverse from 1 past their max range */
- if (state->wraps)
- state->reverse_val -= INPUT_RELATIVE_PER_PIXEL;
+ unicode_char ch = field.keyboard_code(which);
+ if (ch == 0)
+ break;
+ name.catprintf("%-*s ", MAX(SPACE_COUNT - 1, 0), field.manager().natkeyboard().key_name(tempstr, ch));
}
- }
- /* compute scale for keypresses */
- state->keyscalepos = RECIP_SCALE(state->scalepos);
- state->keyscaleneg = RECIP_SCALE(state->scaleneg);
+ // trim extra spaces
+ name.trimspace();
- return state;
+ // special case
+ if (name.len() == 0)
+ name.cpy("Unnamed Key");
+ }
}
-/***************************************************************************
- ONCE-PER-FRAME UPDATES
-***************************************************************************/
+//**************************************************************************
+// I/O PORT
+//**************************************************************************
-/*-------------------------------------------------
- frame_update_callback - system-wide callback to
- update the input ports once per frame, but
- only if we are not paused
--------------------------------------------------*/
+//-------------------------------------------------
+// ioport_port - constructor
+//-------------------------------------------------
-static void frame_update_callback(running_machine &machine)
+ioport_port::ioport_port(device_t &owner, const char *tag)
+ : m_next(NULL),
+ m_device(owner),
+ m_tag(tag),
+ m_modcount(0),
+ m_active(0),
+ m_live(NULL)
{
- /* if we're paused, don't do anything */
- if (machine.paused())
- return;
-
- /* otherwise, use the common code */
- frame_update(machine);
}
-static key_buffer *get_buffer(running_machine &machine)
+
+//-------------------------------------------------
+// ~ioport_port - destructor
+//-------------------------------------------------
+
+ioport_port::~ioport_port()
{
- ioport_manager &portdata = machine.ioport();
- assert(inputx_can_post(machine));
- return (key_buffer *)&portdata.keybuffer;
+ global_free(m_live);
}
+//-------------------------------------------------
+// machine - return a reference to the running
+// machine
+//-------------------------------------------------
-static const inputx_code *find_code(inputx_code *codes, unicode_char ch)
+running_machine &ioport_port::machine() const
{
- int i;
-
- assert(codes);
- for (i = 0; codes[i].ch; i++)
- {
- if (codes[i].ch == ch)
- return &codes[i];
- }
- return NULL;
+ return m_device.machine();
}
-/*-------------------------------------------------
- input_port_update_hook - hook function
- called from core to allow for natural keyboard
--------------------------------------------------*/
-static void input_port_update_hook(running_machine &machine, const input_port_config *port, input_port_value *digital)
+//-------------------------------------------------
+// manager - return a reference to the
+// ioport_manager on the running machine
+//-------------------------------------------------
+
+ioport_manager &ioport_port::manager() const
{
- ioport_manager &portdata = machine.ioport();
- const key_buffer *keybuf;
- const inputx_code *code;
- unicode_char ch;
- int i;
- UINT32 value;
+ return machine().ioport();
+}
- if (inputx_can_post(machine))
- {
- keybuf = get_buffer(machine);
- /* is the key down right now? */
- if (keybuf && keybuf->status_keydown && (keybuf->begin_pos != keybuf->end_pos))
- {
- /* identify the character that is down right now, and its component codes */
- ch = keybuf->buffer[keybuf->begin_pos];
- code = find_code(portdata.codes, ch);
+//-------------------------------------------------
+// field - return a pointer to the first field
+// that intersects the given mask
+//-------------------------------------------------
- /* loop through this character's component codes */
- if (code != NULL)
- {
- for (i = 0; i < ARRAY_LENGTH(code->field) && (code->field[i] != NULL); i++)
- {
- if (&code->field[i]->port() == port)
- {
- value = code->field[i]->mask;
- *digital |= value;
- }
- }
- }
- }
- }
+ioport_field *ioport_port::field(ioport_value mask)
+{
+ // if we got the port, look for the field
+ for (ioport_field *field = first_field(); field != NULL; field = field->next())
+ if ((field->mask() & mask) != 0)
+ return field;
+ return NULL;
}
-/*-------------------------------------------------
- frame_update - core logic for per-frame input
- port updating
--------------------------------------------------*/
+//-------------------------------------------------
+// read - return the value of an I/O port
+//-------------------------------------------------
-static void frame_update(running_machine &machine)
+ioport_value ioport_port::read()
{
- ioport_manager &portdata = machine.ioport();
- const input_field_config *mouse_field = NULL;
- int ui_visible = ui_is_menu_active();
- attotime curtime = machine.time();
- const input_port_config *port;
- render_target *mouse_target;
- INT32 mouse_target_x;
- INT32 mouse_target_y;
- int mouse_button;
+ assert_always(manager().safe_to_read(), "Input ports cannot be read at init time!");
-g_profiler.start(PROFILER_INPUT);
+ // start with the digital state
+ ioport_value result = m_live->digital;
- /* record/playback information about the current frame */
- playback_frame(machine, curtime);
- record_frame(machine, curtime);
+ // insert dynamic read values
+ for (dynamic_field *dynfield = m_live->readlist.first(); dynfield != NULL; dynfield = dynfield->next())
+ dynfield->read(result);
- /* track the duration of the previous frame */
- portdata.last_delta_nsec = (curtime - portdata.last_frame_time).as_attoseconds() / ATTOSECONDS_PER_NANOSECOND;
- portdata.last_frame_time = curtime;
+ // apply active high/low state to digital and dynamic read inputs
+ result ^= m_live->defvalue;
- /* update the digital joysticks */
- frame_update_digital_joysticks(machine);
+ // insert analog portions
+ for (analog_field *analog = m_live->analoglist.first(); analog != NULL; analog = analog->next())
+ analog->read(result);
- /* compute default values for all the ports */
- input_port_update_defaults(machine);
+ return result;
+}
- /* perform the mouse hit test */
- mouse_target = ui_input_find_mouse(machine, &mouse_target_x, &mouse_target_y, &mouse_button);
- if (mouse_button && mouse_target)
- {
- const char *tag = NULL;
- input_port_value mask;
- float x, y;
- if (mouse_target->map_point_input(mouse_target_x, mouse_target_y, tag, mask, x, y))
- mouse_field = input_field_by_tag_and_mask(machine, tag, mask);
- }
- /* loop over all input ports */
- for (port = machine.ioport().first_port(); port != NULL; port = port->next())
- {
- const input_field_config *field;
- device_field_info *device_field;
- input_port_value newvalue;
+//-------------------------------------------------
+// write - write a value to a port
+//-------------------------------------------------
- /* start with 0 values for the digital and VBLANK bits */
- port->state->digital = 0;
- port->state->vblank = 0;
+void ioport_port::write(ioport_value data, ioport_value mem_mask)
+{
+ // call device line write handlers
+ COMBINE_DATA(&m_live->outputvalue);
+ for (dynamic_field *dynfield = m_live->writelist.first(); dynfield != NULL; dynfield = dynfield->next())
+ if (dynfield->field().type() == IPT_OUTPUT)
+ dynfield->write(m_live->outputvalue);
+}
- /* now loop back and modify based on the inputs */
- for (field = port->first_field(); field != NULL; field = field->next())
- if (input_condition_true(port->machine(), &field->condition, port->owner()))
- {
- /* accumulate VBLANK bits */
- if (field->type == IPT_VBLANK)
- port->state->vblank ^= field->mask;
- /* handle analog inputs */
- else if (field->state->analog != NULL)
- frame_update_analog_field(machine, field->state->analog);
+//-------------------------------------------------
+// frame_update - once/frame update
+//-------------------------------------------------
- /* handle non-analog types, but only when the UI isn't visible */
- else if (!ui_visible && frame_get_digital_field_state(field, field == mouse_field))
- port->state->digital |= field->mask;
- }
+void ioport_port::frame_update(ioport_field *mouse_field)
+{
+ // start with 0 values for the digital bits
+ m_live->digital = 0;
- /* hook for MESS's natural keyboard support */
- input_port_update_hook(machine, port, &port->state->digital);
+ // now loop back and modify based on the inputs
+ for (ioport_field *field = first_field(); field != NULL; field = field->next())
+ field->frame_update(m_live->digital, field == mouse_field);
- /* handle playback/record */
- playback_port(port);
- record_port(port);
+ // hook for MESS's natural keyboard support
+ manager().natkeyboard().frame_update(*this, m_live->digital);
- /* call device line write handlers */
- newvalue = input_port_read_direct(port);
- for (device_field = port->state->writedevicelist; device_field; device_field = device_field->next)
- if (device_field->field->type != IPT_OUTPUT && input_condition_true(port->machine(), &device_field->field->condition, port->owner()))
- {
- input_port_value newval = (newvalue & device_field->field->mask) >> device_field->shift;
+ // call device line write handlers
+ ioport_value newvalue = read();
+ for (dynamic_field *dynfield = m_live->writelist.first(); dynfield != NULL; dynfield = dynfield->next())
+ if (dynfield->field().type() != IPT_OUTPUT)
+ dynfield->write(newvalue);
+}
- /* if the bits have write, call the handler */
- if (device_field->oldval != newval)
- {
- device_field->field->write(*device_field->field, device_field->field->write_param, device_field->oldval, newval);
- device_field->oldval = newval;
- }
- }
- }
+//-------------------------------------------------
+// collapse_fields - remove any fields that are
+// wholly overlapped by other fields
+//-------------------------------------------------
-g_profiler.stop();
+void ioport_port::collapse_fields(astring &errorbuf)
+{
+ ioport_value maskbits = 0;
+ int lastmodcount = -1;
+
+ // remove the whole list and start from scratch
+ ioport_field *field = m_fieldlist.detach_all();
+ while (field != NULL)
+ {
+ // if this modcount doesn't match, reset
+ if (field->modcount() != lastmodcount)
+ {
+ lastmodcount = field->modcount();
+ maskbits = 0;
+ }
+
+ // reinsert this field
+ ioport_field *current = field;
+ field = field->next();
+ insert_field(*current, maskbits, errorbuf);
+ }
}
-/*-------------------------------------------------
- frame_update_digital_joysticks - update the
- state of digital joysticks prior to
- accumulating the results in a port
--------------------------------------------------*/
+//-------------------------------------------------
+// insert_field - insert a new field, checking
+// for errors
+//-------------------------------------------------
-static void frame_update_digital_joysticks(running_machine &machine)
+void ioport_port::insert_field(ioport_field &newfield, ioport_value &disallowedbits, astring &errorbuf)
{
- ioport_manager &portdata = machine.ioport();
- int player, joyindex;
+ // verify against the disallowed bits, but only if we are condition-free
+ if (newfield.condition().none())
+ {
+ if ((newfield.mask() & disallowedbits) != 0)
+ errorbuf.catprintf("INPUT_TOKEN_FIELD specifies duplicate port bits (port=%s mask=%X)\n", tag(), newfield.mask());
+ disallowedbits |= newfield.mask();
+ }
- /* loop over all the joysticks */
- for (player = 0; player < MAX_PLAYERS; player++)
- for (joyindex = 0; joyindex < DIGITAL_JOYSTICKS_PER_PLAYER; joyindex++)
+ // first modify/nuke any entries that intersect our maskbits
+ ioport_field *nextfield;
+ for (ioport_field *field = first_field(); field != NULL; field = nextfield)
+ {
+ nextfield = field->next();
+ if ((field->mask() & newfield.mask()) != 0 &&
+ (newfield.condition().none() || field->condition().none() || field->condition() == newfield.condition()))
{
- digital_joystick_state *joystick = &portdata.joystick_info[player][joyindex];
- if (joystick->inuse)
- {
- joystick->previous = joystick->current;
- joystick->current = 0;
-
- /* read all the associated ports */
- if (joystick->field[JOYDIR_UP] != NULL && machine.input().seq_pressed(input_field_seq(joystick->field[JOYDIR_UP], SEQ_TYPE_STANDARD)))
- joystick->current |= JOYDIR_UP_BIT;
- if (joystick->field[JOYDIR_DOWN] != NULL && machine.input().seq_pressed(input_field_seq(joystick->field[JOYDIR_DOWN], SEQ_TYPE_STANDARD)))
- joystick->current |= JOYDIR_DOWN_BIT;
- if (joystick->field[JOYDIR_LEFT] != NULL && machine.input().seq_pressed(input_field_seq(joystick->field[JOYDIR_LEFT], SEQ_TYPE_STANDARD)))
- joystick->current |= JOYDIR_LEFT_BIT;
- if (joystick->field[JOYDIR_RIGHT] != NULL && machine.input().seq_pressed(input_field_seq(joystick->field[JOYDIR_RIGHT], SEQ_TYPE_STANDARD)))
- joystick->current |= JOYDIR_RIGHT_BIT;
-
- /* lock out opposing directions (left + right or up + down) */
- if ((joystick->current & (JOYDIR_UP_BIT | JOYDIR_DOWN_BIT)) == (JOYDIR_UP_BIT | JOYDIR_DOWN_BIT))
- joystick->current &= ~(JOYDIR_UP_BIT | JOYDIR_DOWN_BIT);
- if ((joystick->current & (JOYDIR_LEFT_BIT | JOYDIR_RIGHT_BIT)) == (JOYDIR_LEFT_BIT | JOYDIR_RIGHT_BIT))
- joystick->current &= ~(JOYDIR_LEFT_BIT | JOYDIR_RIGHT_BIT);
-
- /* only update 4-way case if joystick has moved */
- if (joystick->current != joystick->previous)
- {
- joystick->current4way = joystick->current;
+ // reduce the mask of the field we found
+ field->reduce_mask(newfield.mask());
- /*
- If joystick is pointing at a diagonal, acknowledge that the player moved
- the joystick by favoring a direction change. This minimizes frustration
- when using a keyboard for input, and maximizes responsiveness.
+ // if the new entry fully overrides the previous one, we nuke
+ if (INPUT_PORT_OVERRIDE_FULLY_NUKES_PREVIOUS || field->mask() == 0)
+ m_fieldlist.remove(*field);
+ }
+ }
- For example, if you are holding "left" then switch to "up" (where both left
- and up are briefly pressed at the same time), we'll transition immediately
- to "up."
+ // make a mask of just the low bit
+ ioport_value lowbit = (newfield.mask() ^ (newfield.mask() - 1)) & newfield.mask();
- Zero any switches that didn't change from the previous to current state.
- */
- if ((joystick->current4way & (JOYDIR_UP_BIT | JOYDIR_DOWN_BIT)) &&
- (joystick->current4way & (JOYDIR_LEFT_BIT | JOYDIR_RIGHT_BIT)))
- {
- joystick->current4way ^= joystick->current4way & joystick->previous;
- }
+ // scan forward to find where to insert ourselves
+ ioport_field *field;
+ for (field = first_field(); field != NULL; field = field->next())
+ if (field->mask() > lowbit)
+ break;
- /*
- If we are still pointing at a diagonal, we are in an indeterminant state.
+ // insert it into the list
+ m_fieldlist.insert_before(newfield, field);
+}
- This could happen if the player moved the joystick from the idle position directly
- to a diagonal, or from one diagonal directly to an extreme diagonal.
- The chances of this happening with a keyboard are slim, but we still need to
- constrain this case.
+//-------------------------------------------------
+// init_live_state - create the live state
+//-------------------------------------------------
- For now, just resolve randomly.
- */
- if ((joystick->current4way & (JOYDIR_UP_BIT | JOYDIR_DOWN_BIT)) &&
- (joystick->current4way & (JOYDIR_LEFT_BIT | JOYDIR_RIGHT_BIT)))
- {
- if (machine.rand() & 1)
- joystick->current4way &= ~(JOYDIR_LEFT_BIT | JOYDIR_RIGHT_BIT);
- else
- joystick->current4way &= ~(JOYDIR_UP_BIT | JOYDIR_DOWN_BIT);
- }
- }
- }
- }
+void ioport_port::init_live_state()
+{
+ m_live = global_alloc(ioport_port_live(*this));
}
-/*-------------------------------------------------
- frame_update_analog_field - update the
- internals of a single analog field
--------------------------------------------------*/
-
-static void frame_update_analog_field(running_machine &machine, analog_field_state *analog)
-{
- input_item_class itemclass;
- int keypressed = FALSE;
- INT64 keyscale;
- INT32 rawvalue;
- INT32 delta = 0;
- /* clamp the previous value to the min/max range and remember it */
- analog->previous = analog->accum = apply_analog_min_max(analog, analog->accum);
+//**************************************************************************
+// I/O PORT LIVE STATE
+//**************************************************************************
- /* get the new raw analog value and its type */
- rawvalue = machine.input().seq_axis_value(input_field_seq(analog->field, SEQ_TYPE_STANDARD), itemclass);
+//-------------------------------------------------
+// ioport_port_live - constructor
+//-------------------------------------------------
- /* if we got an absolute input, it overrides everything else */
- if (itemclass == ITEM_CLASS_ABSOLUTE)
+ioport_port_live::ioport_port_live(ioport_port &port)
+ : defvalue(0),
+ digital(0),
+ outputvalue(0)
+{
+ // iterate over fields
+ for (ioport_field *field = port.first_field(); field != NULL; field = field->next())
{
- if (analog->previousanalog != rawvalue)
- {
- /* only update if analog value changed */
- analog->previousanalog = rawvalue;
+ // allocate analog state if it's analog
+ analog_field *analog = NULL;
+ if (field->is_analog())
+ analog = &analoglist.append(*global_alloc(analog_field(*field)));
+
+ // allocate a dynamic field for reading
+ if (field->has_dynamic_read())
+ readlist.append(*global_alloc(dynamic_field(*field)));
+
+ // allocate a dynamic field for writing
+ if (field->has_dynamic_write())
+ writelist.append(*global_alloc(dynamic_field(*field)));
+
+ // let the field initialize its live state
+ field->init_live_state(analog);
+ }
+}
- /* apply the inverse of the sensitivity to the raw value so that */
- /* it will still cover the full min->max range requested after */
- /* we apply the sensitivity adjustment */
- if (analog->absolute || (analog->field->flags & ANALOG_FLAG_RESET))
- {
- /* if port is absolute, then just return the absolute data supplied */
- analog->accum = APPLY_INVERSE_SENSITIVITY(rawvalue, analog->sensitivity);
- }
- else if (analog->positionalscale != 0)
- {
- /* if port is positional, we will take the full analog control and divide it */
- /* into positions, that way as the control is moved full scale, */
- /* it moves through all the positions */
- rawvalue = APPLY_SCALE(rawvalue - INPUT_ABSOLUTE_MIN, analog->positionalscale) * INPUT_RELATIVE_PER_PIXEL + analog->minimum;
-
- /* clamp the high value so it does not roll over */
- rawvalue = MIN(rawvalue, analog->maximum);
- analog->accum = APPLY_INVERSE_SENSITIVITY(rawvalue, analog->sensitivity);
- }
- else
- /* if port is relative, we use the value to simulate the speed of relative movement */
- /* sensitivity adjustment is allowed for this mode */
- analog->accum += rawvalue;
- analog->lastdigital = FALSE;
- /* do not bother with other control types if the analog data is changing */
- return;
- }
- else
- {
- /* we still have to update fake relative from joystick control */
- if (!analog->absolute && analog->positionalscale == 0)
- analog->accum += rawvalue;
- }
- }
- /* if we got it from a relative device, use that as the starting delta */
- /* also note that the last input was not a digital one */
- if (itemclass == ITEM_CLASS_RELATIVE && rawvalue != 0)
- {
- delta = rawvalue;
- analog->lastdigital = FALSE;
- }
+//**************************************************************************
+// I/O PORT MANAGER
+//**************************************************************************
- keyscale = (analog->accum >= 0) ? analog->keyscalepos : analog->keyscaleneg;
+//-------------------------------------------------
+// ioport_manager - constructor
+//-------------------------------------------------
- /* if the decrement code sequence is pressed, add the key delta to */
- /* the accumulated delta; also note that the last input was a digital one */
- if (machine.input().seq_pressed(input_field_seq(analog->field, SEQ_TYPE_DECREMENT)))
- {
- keypressed = TRUE;
- if (analog->delta != 0)
- delta -= APPLY_SCALE(analog->delta, keyscale);
- else if (!analog->lastdigital)
- /* decrement only once when first pressed */
- delta -= APPLY_SCALE(1, keyscale);
- analog->lastdigital = TRUE;
- }
+ioport_manager::ioport_manager(running_machine &machine)
+ : m_machine(machine),
+ m_safe_to_read(false),
+ m_natkeyboard(machine),
+ m_last_frame_time(attotime::zero),
+ m_last_delta_nsec(0),
+ m_record_file(machine.options().input_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS),
+ m_playback_file(machine.options().input_directory(), OPEN_FLAG_READ),
+ m_playback_accumulated_speed(0),
+ m_playback_accumulated_frames(0)
+{
+ memset(m_type_to_entry, 0, sizeof(m_type_to_entry));
+}
- /* same for the increment code sequence */
- if (machine.input().seq_pressed(input_field_seq(analog->field, SEQ_TYPE_INCREMENT)))
- {
- keypressed = TRUE;
- if (analog->delta)
- delta += APPLY_SCALE(analog->delta, keyscale);
- else if (!analog->lastdigital)
- /* increment only once when first pressed */
- delta += APPLY_SCALE(1, keyscale);
- analog->lastdigital = TRUE;
- }
- /* if resetting is requested, clear the accumulated position to 0 before */
- /* applying the deltas so that we only return this frame's delta */
- /* note that centering only works for relative controls */
- /* no need to check if absolute here because it is checked by the validity tests */
- if (analog->field->flags & ANALOG_FLAG_RESET)
- analog->accum = 0;
+//-------------------------------------------------
+// initialize - walk the configured ports and
+// create live state information
+//-------------------------------------------------
+
+time_t ioport_manager::initialize()
+{
+ // add an exit callback and a frame callback
+ machine().add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(ioport_manager::exit), this));
+ machine().add_notifier(MACHINE_NOTIFY_FRAME, machine_notify_delegate(FUNC(ioport_manager::frame_update), this));
- /* apply the delta to the accumulated value */
- analog->accum += delta;
+ // initialize the default port info from the OSD
+ init_port_types();
- /* if our last movement was due to a digital input, and if this control */
- /* type autocenters, and if neither the increment nor the decrement seq */
- /* was pressed, apply autocentering */
- if (analog->autocenter)
+ // if we have a token list, proceed
+ device_iterator iter(machine().root_device());
+ for (device_t *device = iter.first(); device != NULL; device = iter.next())
{
- INT32 center = APPLY_INVERSE_SENSITIVITY(analog->center, analog->sensitivity);
- if (analog->lastdigital && !keypressed)
- {
- /* autocenter from positive values */
- if (analog->accum >= center)
- {
- analog->accum -= APPLY_SCALE(analog->centerdelta, analog->keyscalepos);
- if (analog->accum < center)
- {
- analog->accum = center;
- analog->lastdigital = FALSE;
- }
- }
+ astring errors;
+ m_portlist.append(*device, errors);
+ if (errors)
+ mame_printf_error("Input port errors:\n%s", errors.cstr());
+ }
- /* autocenter from negative values */
- else
- {
- analog->accum += APPLY_SCALE(analog->centerdelta, analog->keyscaleneg);
- if (analog->accum > center)
+ // allocate live structures to mirror the configuration
+ for (ioport_port *port = first_port(); port != NULL; port = port->next())
+ port->init_live_state();
+
+ // handle autoselection of devices
+ init_autoselect_devices(IPT_AD_STICK_X, IPT_AD_STICK_Y, IPT_AD_STICK_Z, OPTION_ADSTICK_DEVICE, "analog joystick");
+ init_autoselect_devices(IPT_PADDLE, IPT_PADDLE_V, 0, OPTION_PADDLE_DEVICE, "paddle");
+ init_autoselect_devices(IPT_PEDAL, IPT_PEDAL2, IPT_PEDAL3, OPTION_PEDAL_DEVICE, "pedal");
+ init_autoselect_devices(IPT_LIGHTGUN_X, IPT_LIGHTGUN_Y, 0, OPTION_LIGHTGUN_DEVICE, "lightgun");
+ init_autoselect_devices(IPT_POSITIONAL, IPT_POSITIONAL_V, 0, OPTION_POSITIONAL_DEVICE, "positional");
+ init_autoselect_devices(IPT_DIAL, IPT_DIAL_V, 0, OPTION_DIAL_DEVICE, "dial");
+ init_autoselect_devices(IPT_TRACKBALL_X, IPT_TRACKBALL_Y, 0, OPTION_TRACKBALL_DEVICE, "trackball");
+ init_autoselect_devices(IPT_MOUSE_X, IPT_MOUSE_Y, 0, OPTION_MOUSE_DEVICE, "mouse");
+
+ // look for 4-way joysticks and change the default map if we find any
+ const char *joystick_map_default = machine().options().joystick_map();
+ if (joystick_map_default[0] == 0 || strcmp(joystick_map_default, "auto") == 0)
+ for (ioport_port *port = first_port(); port != NULL; port = port->next())
+ for (ioport_field *field = port->first_field(); field != NULL; field = field->next())
+ if (field->live().joystick != NULL && field->way() == 4)
{
- analog->accum = center;
- analog->lastdigital = FALSE;
+ machine().input().set_global_joystick_map(field->rotated() ? joystick_map_4way_diagonal : joystick_map_4way_sticky);
+ break;
}
- }
- }
- }
- else if (!keypressed)
- analog->lastdigital = FALSE;
+
+ // register callbacks for when we load configurations
+ config_register(machine(), "input", config_saveload_delegate(FUNC(ioport_manager::load_config), this), config_saveload_delegate(FUNC(ioport_manager::save_config), this));
+
+ // open playback and record files if specified
+ time_t basetime = playback_init();
+ record_init();
+ return basetime;
}
-/*-------------------------------------------------
- frame_get_digital_field_state - get the state
- of a digital field
--------------------------------------------------*/
+//-------------------------------------------------
+// init_port_types - initialize the default
+// type list
+//-------------------------------------------------
-static int frame_get_digital_field_state(const input_field_config *field, int mouse_down)
+void ioport_manager::init_port_types()
{
- int curstate = mouse_down || field->machine().input().seq_pressed(input_field_seq(field, SEQ_TYPE_STANDARD));
- int changed = FALSE;
- int temp_field_impulse;
+ // convert the array into a list of type states that can be modified
+ construct_core_types(m_typelist);
- /* if the state changed, look for switch down/switch up */
- if (curstate != field->state->last)
+ // ask the OSD to customize the list
+ machine().osd().customize_input_type_list(m_typelist);
+
+ // now iterate over the OSD-modified types
+ for (input_type_entry *curtype = first_type(); curtype != NULL; curtype = curtype->next())
{
- field->state->last = curstate;
- changed = TRUE;
+ // first copy all the OSD-updated sequences into our current state
+ for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++)
+ curtype->m_seq[seqtype] = curtype->defseq(seqtype);
+
+ // also make a lookup table mapping type/player to the appropriate type list entry
+ m_type_to_entry[curtype->type()][curtype->player()] = curtype;
}
+}
- if (field->type == IPT_KEYBOARD && ui_get_use_natural_keyboard(field->machine()))
- return FALSE;
- /* coin impulse option */
- {
- int temp_option_impulse = field->machine().options().coin_impulse();
- temp_field_impulse = field->impulse;
- if ( temp_option_impulse != 0)
- {
- if (temp_option_impulse < 0)
- temp_field_impulse = 0;
- else if ((field->type >= IPT_COIN1 && field->type <= IPT_COIN12) || field->impulse != 0)
- temp_field_impulse = temp_option_impulse;
- }
- }
+//-------------------------------------------------
+// init_autoselect_devices - autoselect a single
+// device based on the input port list passed
+// in and the corresponding option
+//-------------------------------------------------
- /* if this is a switch-down event, handle impulse and toggle */
- if (changed && curstate)
- {
- /* impluse controls: reset the impulse counter */
- if (temp_field_impulse != 0 && field->state->impulse == 0)
- field->state->impulse = temp_field_impulse;
+void ioport_manager::init_autoselect_devices(int type1, int type2, int type3, const char *option, const char *ananame)
+{
+ // if nothing specified, ignore the option
+ const char *stemp = machine().options().value(option);
+ if (stemp[0] == 0)
+ return;
- /* toggle controls: flip the toggle state or advance to the next setting */
- if (field->flags & FIELD_FLAG_TOGGLE)
- {
- if (field->settinglist().count() == 0)
- field->state->value ^= field->mask;
- else
- input_field_select_next_setting(field);
- }
+ // extract valid strings
+ const char *autostring = "keyboard";
+ input_device_class autoenable = DEVICE_CLASS_KEYBOARD;
+ if (strcmp(stemp, "mouse") == 0)
+ {
+ autoenable = DEVICE_CLASS_MOUSE;
+ autostring = "mouse";
}
-
- /* update the current state with the impulse state */
- if (temp_field_impulse != 0)
+ else if (strcmp(stemp, "joystick") == 0)
{
- if (field->state->impulse != 0)
- {
- field->state->impulse--;
- curstate = TRUE;
- }
- else
- curstate = FALSE;
+ autoenable = DEVICE_CLASS_JOYSTICK;
+ autostring = "joystick";
}
-
- /* for toggle switches, the current value is folded into the port's default value */
- /* so we always return FALSE here */
- if (field->flags & FIELD_FLAG_TOGGLE)
- curstate = FALSE;
-
- /* additional logic to restrict digital joysticks */
- if (curstate && !mouse_down && field->state->joystick != NULL && field->way != 16 && !field->machine().options().joystick_contradictory())
+ else if (strcmp(stemp, "lightgun") == 0)
{
- UINT8 mask = (field->way == 4) ? field->state->joystick->current4way : field->state->joystick->current;
- if (!(mask & (1 << field->state->joydir)))
- curstate = FALSE;
+ autoenable = DEVICE_CLASS_LIGHTGUN;
+ autostring = "lightgun";
}
-
- /* skip locked-out coin inputs */
- if (curstate && field->type >= IPT_COIN1 && field->type <= IPT_COIN12 && coin_lockout_get_state(field->machine(), field->type - IPT_COIN1))
+ else if (strcmp(stemp, "none") == 0)
{
- int verbose = field->machine().options().verbose();
-#ifdef MAME_DEBUG
- verbose = 1;
-#endif
- if (field->machine().options().coin_lockout())
- {
- if (verbose)
- ui_popup_time(3, "Coinlock disabled %s.", input_field_name(field));
- return FALSE; /* curstate = FALSE; */
- }
- else
- if (verbose)
- ui_popup_time(3, "Coinlock disabled, but broken through %s.", input_field_name(field));
+ // nothing specified
+ return;
}
+ else if (strcmp(stemp, "keyboard") != 0)
+ mame_printf_error("Invalid %s value %s; reverting to keyboard\n", option, stemp);
+
+ // only scan the list if we haven't already enabled this class of control
+ if (first_port() != NULL && !machine().input().device_class(autoenable).enabled())
+ for (ioport_port *port = first_port(); port != NULL; port = port->next())
+ for (ioport_field *field = port->first_field(); field != NULL; field = field->next())
- return curstate;
+ // if this port type is in use, apply the autoselect criteria
+ if ((type1 != 0 && field->type() == type1) || (type2 != 0 && field->type() == type2) || (type3 != 0 && field->type() == type3))
+ {
+ mame_printf_verbose("Input: Autoenabling %s due to presence of a %s\n", autostring, ananame);
+ machine().input().device_class(autoenable).enable();
+ break;
+ }
}
+//-------------------------------------------------
+// exit - exit callback to ensure we clean up
+// and close our files
+//-------------------------------------------------
-/***************************************************************************
- PORT CONFIGURATION HELPERS
-***************************************************************************/
-
-/*-------------------------------------------------
- port_default_value - updates default value
- of port settings according to device settings
--------------------------------------------------*/
-
-UINT32 port_default_value(const char *fulltag, UINT32 mask, UINT32 defval, device_t &owner)
+void ioport_manager::exit()
{
- const input_device_default *def = owner.input_ports_defaults();
- if (def != NULL)
- {
- astring fullpath;
- for ( ; def->tag != NULL; def++)
- if (owner.subtag(fullpath, def->tag) == fulltag && def->mask == mask)
- return def->defvalue;
- }
- return defval;
+ // close any playback or recording files
+ playback_end();
+ record_end();
}
-/*-------------------------------------------------
- input_port_config - constructor for an
- I/O port configuration object
--------------------------------------------------*/
+//-------------------------------------------------
+// type_name - return the name for the given
+// type/player
+//-------------------------------------------------
-input_port_config::input_port_config(device_t &owner, const char *tag)
- : state(NULL),
- active(0),
- m_next(NULL),
- m_owner(owner),
- m_tag(tag),
- m_modcount(0)
+const char *ioport_manager::type_name(ioport_type type, UINT8 player)
{
+ // if we have a machine, use the live state and quick lookup
+ input_type_entry *entry = m_type_to_entry[type][player];
+ if (entry != NULL)
+ return entry->name();
+
+ // if we find nothing, return an invalid group
+ return "???";
}
-running_machine &input_port_config::machine() const
+//-------------------------------------------------
+// type_group - return the group for the given
+// type/player
+//-------------------------------------------------
+
+ioport_group ioport_manager::type_group(ioport_type type, int player)
{
- return m_owner.machine();
+ input_type_entry *entry = m_type_to_entry[type][player];
+ if (entry != NULL)
+ return entry->group();
+
+ // if we find nothing, return an invalid group
+ return IPG_INVALID;
}
-/*-------------------------------------------------
- field_config_alloc - allocate a new input
- port field config
--------------------------------------------------*/
+//-------------------------------------------------
+// type_seq - return the input sequence for the
+// given type/player
+//-------------------------------------------------
-input_field_config::input_field_config(input_port_config &port, int _type, input_port_value _defvalue, input_port_value _maskbits, const char *_name)
- : mask(_maskbits),
- defvalue(_defvalue & _maskbits),
- type(_type),
- player(0),
- flags(0),
- impulse(0),
- name(_name),
- read_param(NULL),
- read_device(DEVICE_SELF),
- write_param(NULL),
- write_device(DEVICE_SELF),
- min(0),
- max(_maskbits),
- sensitivity(0),
- delta(0),
- centerdelta(0),
- crossaxis(0),
- crossscale(0),
- crossoffset(0),
- crossaltaxis(0),
- crossmapper_device(DEVICE_SELF),
- full_turn_count(0),
- remap_table(NULL),
- way(0),
- state(NULL),
- m_next(NULL),
- m_port(port),
- m_modcount(port.modcount())
+const input_seq &ioport_manager::type_seq(ioport_type type, int player, input_seq_type seqtype)
{
- memset(&condition, 0, sizeof(condition));
- for (int seqtype = 0; seqtype < ARRAY_LENGTH(seq); seqtype++)
- seq[seqtype].set_default();
- chars[0] = chars[1] = chars[2] = (unicode_char) 0;
+ assert(type >= 0 && type < IPT_COUNT);
+ assert(player >= 0 && player < MAX_PLAYERS);
+
+ // if we have a machine, use the live state and quick lookup
+ input_type_entry *entry = m_type_to_entry[type][player];
+ if (entry != NULL)
+ return entry->seq(seqtype);
+
+ // if we find nothing, return an empty sequence
+ return input_seq::empty_seq;
}
-input_setting_config::input_setting_config(input_field_config &field, input_port_value _value, const char *_name)
- : value(_value),
- name(_name),
- m_field(field),
- m_next(NULL)
+//-------------------------------------------------
+// set_type_seq - change the input sequence for
+// the given type/player
+//-------------------------------------------------
+
+void ioport_manager::set_type_seq(ioport_type type, int player, input_seq_type seqtype, const input_seq &newseq)
{
- memset(&condition, 0, sizeof(condition));
+ input_type_entry *entry = m_type_to_entry[type][player];
+ if (entry != NULL)
+ entry->m_seq[seqtype] = newseq;
}
-input_field_diplocation::input_field_diplocation(const char *string, UINT8 _swnum, bool _invert)
- : swname(string),
- swnum(_swnum),
- invert(_invert)
+
+//-------------------------------------------------
+// type_pressed - return true if the sequence for
+// the given input type/player is pressed
+//-------------------------------------------------
+
+bool ioport_manager::type_pressed(ioport_type type, int player)
{
+ return machine().input().seq_pressed(type_seq(type, player));
}
-/*-------------------------------------------------
- field_config_insert - insert an allocated
- input port field config, replacing any
- intersecting fields already present and
- inserting at the correct sorted location
--------------------------------------------------*/
-void input_port_config::collapse_fields(astring &errorbuf)
+//-------------------------------------------------
+// type_class_present - return true if the given
+// ioport_type_class exists in at least one port
+//-------------------------------------------------
+
+bool ioport_manager::type_class_present(ioport_type_class inputclass)
{
- input_field_config *list = m_fieldlist.detach_all();
- input_port_value maskbits = 0;
- int lastmodcount = -1;
- while (list != NULL)
- {
- if (list->modcount() != lastmodcount)
- {
- lastmodcount = list->modcount();
- maskbits = 0;
- }
- input_field_config *current = list;
- list = list->next();
- field_config_insert(*current, maskbits, errorbuf);
- }
+ for (ioport_port *port = first_port(); port != NULL; port = port->next())
+ for (ioport_field *field = port->first_field(); field != NULL; field = field->next())
+ if (field->type_class() == inputclass)
+ return true;
+ return false;
}
-void field_config_insert(input_field_config &newfield, input_port_value &disallowedbits, astring &errorbuf)
-{
- input_port_value lowbit;
- /* verify against the disallowed bits, but only if we are condition-free */
- if (newfield.condition.condition == PORTCOND_ALWAYS)
- {
- if ((newfield.mask & disallowedbits) != 0)
- errorbuf.catprintf("INPUT_TOKEN_FIELD specifies duplicate port bits (port=%s mask=%X)\n", newfield.port().tag(), newfield.mask);
- disallowedbits |= newfield.mask;
- }
+//-------------------------------------------------
+// has_keyboard - determine if there is a
+// keyboard present in the control list
+//-------------------------------------------------
- /* first modify/nuke any entries that intersect our maskbits */
- input_field_config *nextfield;
- for (input_field_config *field = newfield.port().fieldlist().first(); field != NULL; field = nextfield)
- {
- nextfield = field->next();
- if ((field->mask & newfield.mask) != 0 && (newfield.condition.condition == PORTCOND_ALWAYS ||
- field->condition.condition == PORTCOND_ALWAYS ||
- condition_equal(&field->condition, &newfield.condition)))
+bool ioport_manager::has_keyboard() const
+{
+ // iterate over ports and fields
+ for (ioport_port *port = first_port(); port != NULL; port = port->next())
+ for (ioport_field *field = port->first_field(); field != NULL; field = field->next())
{
- /* reduce the mask of the field we found */
- field->mask &= ~newfield.mask;
+ // if we are at init, check IPT_KEYBOARD
+ if (!m_safe_to_read && field->type() == IPT_KEYBOARD)
+ return true;
- /* if the new entry fully overrides the previous one, we nuke */
- if (INPUT_PORT_OVERRIDE_FULLY_NUKES_PREVIOUS || field->mask == 0)
- newfield.port().fieldlist().remove(*field);
+ // else, check if there is a keyboard and if such a keyboard is enabled
+ if (field->type() == IPT_KEYBOARD && field->enabled())
+ return true;
}
- }
- /* make a mask of just the low bit */
- lowbit = (newfield.mask ^ (newfield.mask - 1)) & newfield.mask;
+ return false;
+}
+
+//-------------------------------------------------
+// count_players - counts the number of active
+// players
+//-------------------------------------------------
- /* scan forward to find where to insert ourselves */
- input_field_config *field;
- for (field = newfield.port().fieldlist().first(); field != NULL; field = field->next())
- if (field->mask > lowbit)
- break;
+int ioport_manager::count_players() const
+{
+ int max_player = 0;
+ for (ioport_port *port = first_port(); port != NULL; port = port->next())
+ for (ioport_field *field = port->first_field(); field != NULL; field = field->next())
+ if (field->type_class() == INPUT_CLASS_CONTROLLER && max_player <= field->player() + 1)
+ max_player = field->player() + 1;
- /* insert it into the list */
- newfield.port().fieldlist().insert_before(newfield, field);
+ return max_player;
}
-/*-------------------------------------------------
- diplocation_expand - expand a string-based
- DIP location into a linked list of
- descriptions
--------------------------------------------------*/
+//-------------------------------------------------
+// crosshair_position - return the extracted
+// crosshair values for the given player
+//-------------------------------------------------
-void diplocation_list_alloc(input_field_config &field, const char *location, astring &errorbuf)
+bool ioport_manager::crosshair_position(int player, float &x, float &y)
{
- /* if nothing present, bail */
- if (location == NULL)
- return;
-
- field.diploclist().reset();
+ // read all the lightgun values
+ bool gotx = false, goty = false;
+ for (ioport_port *port = first_port(); port != NULL; port = port->next())
+ for (ioport_field *field = port->first_field(); field != NULL; field = field->next())
+ if (field->player() == player && field->crosshair_axis() != CROSSHAIR_AXIS_NONE && field->enabled())
+ {
+ field->crosshair_position(x, y, gotx, goty);
- /* parse the string */
- astring name; // Don't move this variable inside the loop, lastname's lifetime depends on it being outside
- const char *lastname = NULL;
- const char *curentry = location;
- int entries = 0;
- while (*curentry != 0)
- {
- /* find the end of this entry */
- const char *comma = strchr(curentry, ',');
- if (comma == NULL)
- comma = curentry + strlen(curentry);
+ // if we got both, stop
+ if (gotx && goty)
+ break;
+ }
- /* extract it to tempbuf */
- astring tempstr;
- tempstr.cpy(curentry, comma - curentry);
+ return (gotx && goty);
+}
- /* first extract the switch name if present */
- const char *number = tempstr;
- const char *colon = strchr(tempstr, ':');
- /* allocate and copy the name if it is present */
- if (colon != NULL)
- {
- lastname = name.cpy(number, colon - number);
- number = colon + 1;
- }
+//-------------------------------------------------
+// update_defaults - force an update to the input
+// port values based on current conditions
+//-------------------------------------------------
- /* otherwise, just copy the last name */
- else
+void ioport_manager::update_defaults()
+{
+ // two passes to catch conditionals properly
+ for (int loopnum = 0; loopnum < 2; loopnum++)
+ {
+ // loop over all input ports
+ for (ioport_port *port = first_port(); port != NULL; port = port->next())
{
- if (lastname == NULL)
- {
- errorbuf.catprintf("Switch location '%s' missing switch name!\n", location);
- lastname = (char *)"UNK";
- }
- name.cpy(lastname);
- }
+ // only clear on the first pass
+ if (loopnum == 0)
+ port->live().defvalue = 0;
- /* if the number is preceded by a '!' it's active high */
- bool invert = false;
- if (*number == '!')
- {
- invert = true;
- number++;
+ // first compute the default value for the entire port
+ for (ioport_field *field = port->first_field(); field != NULL; field = field->next())
+ if (field->enabled())
+ port->live().defvalue = (port->live().defvalue & ~field->mask()) | (field->live().value & field->mask());
}
+ }
+}
- /* now scan the switch number */
- int swnum = -1;
- if (sscanf(number, "%d", &swnum) != 1)
- errorbuf.catprintf("Switch location '%s' has invalid format!\n", location);
-
- /* allocate a new entry */
- field.diploclist().append(*global_alloc(input_field_diplocation(name, swnum, invert)));
- entries++;
- /* advance to the next item */
- curentry = comma;
- if (*curentry != 0)
- curentry++;
- }
+//-------------------------------------------------
+// frame_update - core logic for per-frame input
+// port updating
+//-------------------------------------------------
- /* then verify the number of bits in the mask matches */
- input_port_value temp;
- int bits;
- for (bits = 0, temp = field.mask; temp != 0 && bits < 32; bits++)
- temp &= temp - 1;
- if (bits != entries)
- errorbuf.catprintf("Switch location '%s' does not describe enough bits for mask %X\n", location, field.mask);
+digital_joystick &ioport_manager::digjoystick(int player, int number)
+{
+ // find it in the list
+ for (digital_joystick *joystick = m_joystick_list.first(); joystick != NULL; joystick = joystick->next())
+ if (joystick->player() == player && joystick->number() == number)
+ return *joystick;
+
+ // create a new one
+ return m_joystick_list.append(*global_alloc(digital_joystick(player, number)));
}
+//-------------------------------------------------
+// frame_update - core logic for per-frame input
+// port updating
+//-------------------------------------------------
-/***************************************************************************
- TOKENIZATION HELPERS
-***************************************************************************/
+void ioport_manager::frame_update()
+{
+ // if we're paused, don't do anything
+ if (machine().paused())
+ return;
-/*-------------------------------------------------
- token_to_input_field_type - convert a string
- token to an input field type and player
--------------------------------------------------*/
+g_profiler.start(PROFILER_INPUT);
-static int token_to_input_field_type(running_machine &machine, const char *string, int *player)
-{
- ioport_manager &portdata = machine.ioport();
- int ipnum;
+ // record/playback information about the current frame
+ attotime curtime = machine().time();
+ playback_frame(curtime);
+ record_frame(curtime);
- /* check for our failsafe case first */
- if (sscanf(string, "TYPE_OTHER(%d,%d)", &ipnum, player) == 2)
- return ipnum;
+ // track the duration of the previous frame
+ m_last_delta_nsec = (curtime - m_last_frame_time).as_attoseconds() / ATTOSECONDS_PER_NANOSECOND;
+ m_last_frame_time = curtime;
- /* find the token in the list */
- for (input_type_entry *entry = portdata.typelist.first(); entry != NULL; entry = entry->next())
- if (entry->token != NULL && !strcmp(entry->token, string))
- {
- *player = entry->player;
- return entry->type;
- }
+ // update the digital joysticks
+ for (digital_joystick *joystick = m_joystick_list.first(); joystick != NULL; joystick = joystick->next())
+ joystick->frame_update();
- /* if we fail, return IPT_UNKNOWN */
- *player = 0;
- return IPT_UNKNOWN;
-}
+ // compute default values for all the ports
+ update_defaults();
+ // perform mouse hit testing
+ INT32 mouse_target_x, mouse_target_y;
+ int mouse_button;
+ render_target *mouse_target = ui_input_find_mouse(machine(), &mouse_target_x, &mouse_target_y, &mouse_button);
-/*-------------------------------------------------
- input_field_type_to_token - convert an input
- field type and player to a string token
--------------------------------------------------*/
+ // if the button is pressed, map the point and determine what was hit
+ ioport_field *mouse_field = NULL;
+ if (mouse_button && mouse_target != NULL)
+ {
+ const char *tag = NULL;
+ ioport_value mask;
+ float x, y;
+ if (mouse_target->map_point_input(mouse_target_x, mouse_target_y, tag, mask, x, y))
+ {
+ ioport_port *port = machine().root_device().ioport(tag);
+ if (port != NULL)
+ mouse_field = port->field(mask);
+ }
+ }
-static const char *input_field_type_to_token(running_machine &machine, int type, int player)
-{
- ioport_manager &portdata = machine.ioport();
- static char tempbuf[32];
+ // loop over all input ports
+ for (ioport_port *port = first_port(); port != NULL; port = port->next())
+ {
+ port->frame_update(mouse_field);
- /* look up the port and return the token */
- input_type_entry *entry = portdata.type_to_entry[type][player];
- if (entry != NULL)
- return entry->token;
+ // handle playback/record
+ playback_port(*port);
+ record_port(*port);
+ }
- /* if that fails, carry on */
- sprintf(tempbuf, "TYPE_OTHER(%d,%d)", type, player);
- return tempbuf;
+g_profiler.stop();
}
-/*-------------------------------------------------
- token_to_seq_type - convert a string to
- a sequence type
--------------------------------------------------*/
+//-------------------------------------------------
+// frame_interpolate - interpolate between two
+// values based on the time between frames
+//-------------------------------------------------
-static int token_to_seq_type(const char *string)
+ioport_value ioport_manager::frame_interpolate(ioport_value oldval, ioport_value newval)
{
- int seqindex;
+ // if no last delta, just use new value
+ if (m_last_delta_nsec == 0)
+ return newval;
- /* look up the string in the table of possible sequence types and return the index */
- for (seqindex = 0; seqindex < ARRAY_LENGTH(seqtypestrings); seqindex++)
- if (!mame_stricmp(string, seqtypestrings[seqindex]))
- return seqindex;
-
- return -1;
+ // otherwise, interpolate
+ attoseconds_t nsec_since_last = (machine().time() - m_last_frame_time).as_attoseconds() / ATTOSECONDS_PER_NANOSECOND;
+ return oldval + (INT64(newval - oldval) * nsec_since_last / m_last_delta_nsec);
}
+//-------------------------------------------------
+// load_config - callback to extract configuration
+// data from the XML nodes
+//-------------------------------------------------
-/***************************************************************************
- SETTINGS LOAD
-***************************************************************************/
-
-/*-------------------------------------------------
- load_config_callback - callback to extract
- configuration data from the XML nodes
--------------------------------------------------*/
-
-static void load_config_callback(running_machine &machine, int config_type, xml_data_node *parentnode)
+void ioport_manager::load_config(int config_type, xml_data_node *parentnode)
{
- ioport_manager &portdata = machine.ioport();
- xml_data_node *portnode;
- int seqtype;
-
- /* in the completion phase, we finish the initialization with the final ports */
+ // in the completion phase, we finish the initialization with the final ports
if (config_type == CONFIG_TYPE_FINAL)
{
- portdata.safe_to_read = TRUE;
- frame_update(machine);
+ m_safe_to_read = true;
+ frame_update();
}
- /* early exit if no data to parse */
+ // early exit if no data to parse
if (parentnode == NULL)
return;
- /* iterate over all the remap nodes for controller configs only */
+ // iterate over all the remap nodes for controller configs only
if (config_type == CONFIG_TYPE_CONTROLLER)
- load_remap_table(machine, parentnode);
+ load_remap_table(parentnode);
- /* iterate over all the port nodes */
- for (portnode = xml_get_sibling(parentnode->child, "port"); portnode; portnode = xml_get_sibling(portnode->next, "port"))
+ // iterate over all the port nodes
+ for (xml_data_node *portnode = xml_get_sibling(parentnode->child, "port"); portnode; portnode = xml_get_sibling(portnode->next, "port"))
{
- input_seq newseq[SEQ_TYPE_TOTAL], tempseq;
- xml_data_node *seqnode;
- int type, player;
+ // get the basic port info from the attributes
+ int player;
+ int type = token_to_input_type(xml_get_attribute_string(portnode, "type", ""), player);
- /* get the basic port info from the attributes */
- type = token_to_input_field_type(machine, xml_get_attribute_string(portnode, "type", ""), &player);
-
- /* initialize sequences to invalid defaults */
- for (seqtype = 0; seqtype < ARRAY_LENGTH(newseq); seqtype++)
+ // initialize sequences to invalid defaults
+ input_seq newseq[SEQ_TYPE_TOTAL];
+ for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++)
newseq[seqtype].set(INPUT_CODE_INVALID);
- /* loop over new sequences */
- for (seqnode = xml_get_sibling(portnode->child, "newseq"); seqnode; seqnode = xml_get_sibling(seqnode->next, "newseq"))
+ // loop over new sequences
+ for (xml_data_node *seqnode = xml_get_sibling(portnode->child, "newseq"); seqnode; seqnode = xml_get_sibling(seqnode->next, "newseq"))
{
- /* with a valid type, parse out the new sequence */
- seqtype = token_to_seq_type(xml_get_attribute_string(seqnode, "type", ""));
+ // with a valid type, parse out the new sequence
+ input_seq_type seqtype = token_to_seq_type(xml_get_attribute_string(seqnode, "type", ""));
if (seqtype != -1 && seqnode->value != NULL)
{
if (strcmp(seqnode->value, "NONE") == 0)
newseq[seqtype].set();
else
- machine.input().seq_from_tokens(newseq[seqtype], seqnode->value);
+ machine().input().seq_from_tokens(newseq[seqtype], seqnode->value);
}
}
- /* if we're loading default ports, apply to the defaults */
+ // if we're loading default ports, apply to the defaults
if (config_type != CONFIG_TYPE_GAME)
- load_default_config(machine, portnode, type, player, newseq);
+ load_default_config(portnode, type, player, newseq);
else
- load_game_config(machine, portnode, type, player, newseq);
+ load_game_config(portnode, type, player, newseq);
}
- /* after applying the controller config, push that back into the backup, since that is */
- /* what we will diff against */
+ // after applying the controller config, push that back into the backup, since that is
+ // what we will diff against
if (config_type == CONFIG_TYPE_CONTROLLER)
- for (input_type_entry *entry = portdata.typelist.first(); entry != NULL; entry = entry->next())
- for (seqtype = 0; seqtype < ARRAY_LENGTH(entry->seq); seqtype++)
- entry->defseq[seqtype] = entry->seq[seqtype];
+ for (input_type_entry *entry = m_typelist.first(); entry != NULL; entry = entry->next())
+ for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++)
+ entry->defseq(seqtype) = entry->seq(seqtype);
}
-/*-------------------------------------------------
- load_remap_table - extract and apply the
- global remapping table
--------------------------------------------------*/
+//-------------------------------------------------
+// load_remap_table - extract and apply the
+// global remapping table
+//-------------------------------------------------
-static void load_remap_table(running_machine &machine, xml_data_node *parentnode)
+void ioport_manager::load_remap_table(xml_data_node *parentnode)
{
- ioport_manager &portdata = machine.ioport();
- input_code *oldtable, *newtable;
- xml_data_node *remapnode;
- int count;
-
- /* count items first so we can allocate */
- count = 0;
- for (remapnode = xml_get_sibling(parentnode->child, "remap"); remapnode != NULL; remapnode = xml_get_sibling(remapnode->next, "remap"))
+ // count items first so we can allocate
+ int count = 0;
+ for (xml_data_node *remapnode = xml_get_sibling(parentnode->child, "remap"); remapnode != NULL; remapnode = xml_get_sibling(remapnode->next, "remap"))
count++;
- /* if we have some, deal with them */
+ // if we have some, deal with them
if (count > 0)
{
- int remapnum;
-
- /* allocate tables */
- oldtable = global_alloc_array(input_code, count);
- newtable = global_alloc_array(input_code, count);
+ // allocate tables
+ dynamic_array<input_code> oldtable(count);
+ dynamic_array<input_code> newtable(count);
- /* build up the remap table */
+ // build up the remap table
count = 0;
- for (remapnode = xml_get_sibling(parentnode->child, "remap"); remapnode != NULL; remapnode = xml_get_sibling(remapnode->next, "remap"))
+ for (xml_data_node *remapnode = xml_get_sibling(parentnode->child, "remap"); remapnode != NULL; remapnode = xml_get_sibling(remapnode->next, "remap"))
{
- input_code origcode = machine.input().code_from_token(xml_get_attribute_string(remapnode, "origcode", ""));
- input_code newcode = machine.input().code_from_token(xml_get_attribute_string(remapnode, "newcode", ""));
+ input_code origcode = machine().input().code_from_token(xml_get_attribute_string(remapnode, "origcode", ""));
+ input_code newcode = machine().input().code_from_token(xml_get_attribute_string(remapnode, "newcode", ""));
if (origcode != INPUT_CODE_INVALID && newcode != INPUT_CODE_INVALID)
{
oldtable[count] = origcode;
@@ -3214,214 +3115,187 @@ static void load_remap_table(running_machine &machine, xml_data_node *parentnode
}
}
- /* loop over the remapping table, operating only if something was specified */
- for (remapnum = 0; remapnum < count; remapnum++)
- {
- input_code oldcode = oldtable[remapnum];
- input_code newcode = newtable[remapnum];
-
- /* loop over all default ports, remapping the requested keys */
- for (input_type_entry *entry = portdata.typelist.first(); entry != NULL; entry = entry->next())
- {
- /* remap anything in the default sequences */
- for (int seqtype = 0; seqtype < ARRAY_LENGTH(entry->seq); seqtype++)
- entry->seq[seqtype].replace(oldcode, newcode);
- }
- }
-
- /* release the tables */
- global_free(oldtable);
- global_free(newtable);
+ // loop over the remapping table, then over default ports, replacing old with new
+ for (int remapnum = 0; remapnum < count; remapnum++)
+ for (input_type_entry *entry = m_typelist.first(); entry != NULL; entry = entry->next())
+ for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++)
+ entry->m_seq[seqtype].replace(oldtable[remapnum], newtable[remapnum]);
}
}
-/*-------------------------------------------------
- load_default_config - apply configuration
- data to the default mappings
--------------------------------------------------*/
+//-------------------------------------------------
+// load_default_config - apply configuration
+// data to the default mappings
+//-------------------------------------------------
-static int load_default_config(running_machine &machine, xml_data_node *portnode, int type, int player, const input_seq *newseq)
+bool ioport_manager::load_default_config(xml_data_node *portnode, int type, int player, const input_seq *newseq)
{
- ioport_manager &portdata = machine.ioport();
-
- /* find a matching port in the list */
- for (input_type_entry *entry = portdata.typelist.first(); entry != NULL; entry = entry->next())
- if (entry->type == type && entry->player == player)
+ // find a matching port in the list
+ for (input_type_entry *entry = m_typelist.first(); entry != NULL; entry = entry->next())
+ if (entry->type() == type && entry->player() == player)
{
- for (int seqtype = 0; seqtype < ARRAY_LENGTH(entry->seq); seqtype++)
+ for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++)
if (newseq[seqtype][0] != INPUT_CODE_INVALID)
- entry->seq[seqtype] = newseq[seqtype];
- return TRUE;
+ entry->m_seq[seqtype] = newseq[seqtype];
+ return true;
}
- return FALSE;
+ return false;
}
-/*-------------------------------------------------
- load_game_config - apply configuration
- data to the current set of input ports
--------------------------------------------------*/
+//-------------------------------------------------
+// load_game_config - apply configuration
+// data to the current set of input ports
+//-------------------------------------------------
-static int load_game_config(running_machine &machine, xml_data_node *portnode, int type, int player, const input_seq *newseq)
+bool ioport_manager::load_game_config(xml_data_node *portnode, int type, int player, const input_seq *newseq)
{
- input_port_value mask, defvalue;
- const input_field_config *field;
- const input_port_config *port;
- char tempbuffer[20];
- const char *tag;
-
- /* read the mask, index, and defvalue attributes */
- tag = xml_get_attribute_string(portnode, "tag", NULL);
- mask = xml_get_attribute_int(portnode, "mask", 0);
- defvalue = xml_get_attribute_int(portnode, "defvalue", 0);
+ // read the mask, index, and defvalue attributes
+ const char *tag = xml_get_attribute_string(portnode, "tag", NULL);
+ ioport_value mask = xml_get_attribute_int(portnode, "mask", 0);
+ ioport_value defvalue = xml_get_attribute_int(portnode, "defvalue", 0);
- /* find the port we want; if no tag, search them all */
- for (port = machine.ioport().first_port(); port != NULL; port = port->next())
- if (tag == NULL || strcmp(get_port_tag(port, tempbuffer), tag) == 0)
- for (field = port->first_field(); field != NULL; field = field->next())
+ // find the port we want; if no tag, search them all
+ for (ioport_port *port = first_port(); port != NULL; port = port->next())
+ if (tag == NULL || strcmp(port->tag(), tag) == 0)
+ for (ioport_field *field = port->first_field(); field != NULL; field = field->next())
- /* find the matching mask and defvalue */
- if (field->type == type && field->player == player &&
- field->mask == mask && (field->defvalue & mask) == (defvalue & mask))
+ // find the matching mask and defvalue
+ if (field->type() == type && field->player() == player &&
+ field->mask() == mask && (field->defvalue() & mask) == (defvalue & mask))
{
- const char *revstring;
- int seqtype;
-
- /* if a sequence was specified, copy it in */
- for (seqtype = 0; seqtype < ARRAY_LENGTH(field->state->seq); seqtype++)
+ // if a sequence was specified, copy it in
+ for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++)
if (newseq[seqtype][0] != INPUT_CODE_INVALID)
- field->state->seq[seqtype] = newseq[seqtype];
+ field->live().seq[seqtype] = newseq[seqtype];
- /* for non-analog fields, fetch the value */
- if (field->state->analog == NULL)
- field->state->value = xml_get_attribute_int(portnode, "value", field->defvalue);
+ // for non-analog fields, fetch the value
+ if (field->live().analog == NULL)
+ field->live().value = xml_get_attribute_int(portnode, "value", field->defvalue());
- /* for analog fields, fetch configurable analog attributes */
+ // for analog fields, fetch configurable analog attributes
else
{
- /* get base attributes */
- field->state->analog->delta = xml_get_attribute_int(portnode, "keydelta", field->delta);
- field->state->analog->centerdelta = xml_get_attribute_int(portnode, "centerdelta", field->centerdelta);
- field->state->analog->sensitivity = xml_get_attribute_int(portnode, "sensitivity", field->sensitivity);
+ // get base attributes
+ field->live().analog->m_delta = xml_get_attribute_int(portnode, "keydelta", field->delta());
+ field->live().analog->m_centerdelta = xml_get_attribute_int(portnode, "centerdelta", field->centerdelta());
+ field->live().analog->m_sensitivity = xml_get_attribute_int(portnode, "sensitivity", field->sensitivity());
- /* fetch yes/no for reverse setting */
- revstring = xml_get_attribute_string(portnode, "reverse", NULL);
+ // fetch yes/no for reverse setting
+ const char *revstring = xml_get_attribute_string(portnode, "reverse", NULL);
if (revstring != NULL)
- field->state->analog->reverse = (strcmp(revstring, "yes") == 0);
+ field->live().analog->m_reverse = (strcmp(revstring, "yes") == 0);
}
- return TRUE;
+ return true;
}
- return FALSE;
+ return false;
}
-/***************************************************************************
- SETTINGS SAVE
-***************************************************************************/
+//**************************************************************************
+// SETTINGS SAVE
+//**************************************************************************
-/*-------------------------------------------------
- save_config_callback - config callback for
- saving input port configuration
--------------------------------------------------*/
+//-------------------------------------------------
+// save_config - config callback for saving input
+// port configuration
+//-------------------------------------------------
-static void save_config_callback(running_machine &machine, int config_type, xml_data_node *parentnode)
+void ioport_manager::save_config(int config_type, xml_data_node *parentnode)
{
- /* if no parentnode, ignore */
+ // if no parentnode, ignore
if (parentnode == NULL)
return;
- /* default ports save differently */
+ // default ports save differently
if (config_type == CONFIG_TYPE_DEFAULT)
- save_default_inputs(machine, parentnode);
+ save_default_inputs(parentnode);
else
- save_game_inputs(machine, parentnode);
+ save_game_inputs(parentnode);
}
-/*-------------------------------------------------
- save_sequence - add a node for an input
- sequence
--------------------------------------------------*/
+//-------------------------------------------------
+// save_sequence - add a node for an input
+// sequence
+//-------------------------------------------------
-static void save_sequence(running_machine &machine, xml_data_node *parentnode, int type, int porttype, const input_seq &seq)
+void ioport_manager::save_sequence(xml_data_node *parentnode, input_seq_type type, ioport_type porttype, const input_seq &seq)
{
+ // get the string for the sequence
astring seqstring;
- xml_data_node *seqnode;
-
- /* get the string for the sequence */
if (seq.length() == 0)
seqstring.cpy("NONE");
else
- machine.input().seq_to_tokens(seqstring, seq);
+ machine().input().seq_to_tokens(seqstring, seq);
- /* add the new node */
- seqnode = xml_add_child(parentnode, "newseq", seqstring);
+ // add the new node
+ xml_data_node *seqnode = xml_add_child(parentnode, "newseq", seqstring);
if (seqnode != NULL)
xml_set_attribute(seqnode, "type", seqtypestrings[type]);
}
-/*-------------------------------------------------
- save_this_input_field_type - determine if the given
- port type is worth saving
--------------------------------------------------*/
+//-------------------------------------------------
+// save_this_input_field_type - determine if the
+// given port type is worth saving
+//-------------------------------------------------
-static int save_this_input_field_type(int type)
+bool ioport_manager::save_this_input_field_type(ioport_type type)
{
switch (type)
{
case IPT_UNUSED:
case IPT_END:
case IPT_PORT:
- case IPT_VBLANK:
case IPT_UNKNOWN:
- return FALSE;
+ return false;
+
+ default:
+ break;
}
- return TRUE;
+ return true;
}
-/*-------------------------------------------------
- save_default_inputs - add nodes for any default
- mappings that have changed
--------------------------------------------------*/
+//-------------------------------------------------
+// save_default_inputs - add nodes for any default
+// mappings that have changed
+//-------------------------------------------------
-static void save_default_inputs(running_machine &machine, xml_data_node *parentnode)
+void ioport_manager::save_default_inputs(xml_data_node *parentnode)
{
- ioport_manager &portdata = machine.ioport();
- input_type_entry *entry;
-
- /* iterate over ports */
- for (entry = portdata.typelist.first(); entry != NULL; entry = entry->next())
+ // iterate over ports
+ for (input_type_entry *entry = m_typelist.first(); entry != NULL; entry = entry->next())
{
- /* only save if this port is a type we save */
- if (save_this_input_field_type(entry->type))
+ // only save if this port is a type we save
+ if (save_this_input_field_type(entry->type()))
{
- int seqtype;
-
- /* see if any of the sequences have changed */
- for (seqtype = 0; seqtype < ARRAY_LENGTH(entry->seq); seqtype++)
- if (entry->seq[seqtype] != entry->defseq[seqtype])
+ // see if any of the sequences have changed
+ input_seq_type seqtype;
+ for (seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++)
+ if (entry->seq(seqtype) != entry->defseq(seqtype))
break;
- /* if so, we need to add a node */
- if (seqtype < ARRAY_LENGTH(entry->seq))
+ // if so, we need to add a node
+ if (seqtype < SEQ_TYPE_TOTAL)
{
- /* add a new port node */
+ // add a new port node
xml_data_node *portnode = xml_add_child(parentnode, "port", NULL);
if (portnode != NULL)
{
- /* add the port information and attributes */
- xml_set_attribute(portnode, "type", input_field_type_to_token(machine, entry->type, entry->player));
-
- /* add only the sequences that have changed from the defaults */
- for (seqtype = 0; seqtype < ARRAY_LENGTH(entry->seq); seqtype++)
- if (entry->seq[seqtype] != entry->defseq[seqtype])
- save_sequence(machine, portnode, seqtype, entry->type, entry->seq[seqtype]);
+ // add the port information and attributes
+ astring tempstr;
+ xml_set_attribute(portnode, "type", input_type_to_token(tempstr, entry->type(), entry->player()));
+
+ // add only the sequences that have changed from the defaults
+ for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++)
+ if (entry->seq(seqtype) != entry->defseq(seqtype))
+ save_sequence(portnode, seqtype, entry->type(), entry->seq(seqtype));
}
}
}
@@ -3429,79 +3303,73 @@ static void save_default_inputs(running_machine &machine, xml_data_node *parentn
}
-/*-------------------------------------------------
- save_game_inputs - add nodes for any game
- mappings that have changed
--------------------------------------------------*/
+//-------------------------------------------------
+// save_game_inputs - add nodes for any game
+// mappings that have changed
+//-------------------------------------------------
-static void save_game_inputs(running_machine &machine, xml_data_node *parentnode)
+void ioport_manager::save_game_inputs(xml_data_node *parentnode)
{
- const input_field_config *field;
- const input_port_config *port;
-
- /* iterate over ports */
- for (port = machine.ioport().first_port(); port != NULL; port = port->next())
- for (field = port->first_field(); field != NULL; field = field->next())
- if (save_this_input_field_type(field->type))
+ // iterate over ports
+ for (ioport_port *port = machine().ioport().first_port(); port != NULL; port = port->next())
+ for (ioport_field *field = port->first_field(); field != NULL; field = field->next())
+ if (save_this_input_field_type(field->type()))
{
+ // determine if we changed
bool changed = false;
- int seqtype;
+ for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++)
+ changed |= (field->live().seq[seqtype] != field->seq(seqtype));
- /* determine if we changed */
- for (seqtype = 0; seqtype < ARRAY_LENGTH(field->state->seq); seqtype++)
- changed |= (field->state->seq[seqtype] != field->seq[seqtype]);
+ // non-analog changes
+ if (field->live().analog == NULL)
+ changed |= ((field->live().value & field->mask()) != (field->defvalue() & field->mask()));
- /* non-analog changes */
- if (field->state->analog == NULL)
- changed |= ((field->state->value & field->mask) != (field->defvalue & field->mask));
-
- /* analog changes */
+ // analog changes
else
{
- changed |= (field->state->analog->delta != field->delta);
- changed |= (field->state->analog->centerdelta != field->centerdelta);
- changed |= (field->state->analog->sensitivity != field->sensitivity);
- changed |= (field->state->analog->reverse != ((field->flags & ANALOG_FLAG_REVERSE) != 0));
+ changed |= (field->live().analog->m_delta != field->delta());
+ changed |= (field->live().analog->m_centerdelta != field->centerdelta());
+ changed |= (field->live().analog->m_sensitivity != field->sensitivity());
+ changed |= (field->live().analog->m_reverse != field->analog_reverse());
}
- /* if we did change, add a new node */
+ // if we did change, add a new node
if (changed)
{
- /* add a new port node */
+ // add a new port node
xml_data_node *portnode = xml_add_child(parentnode, "port", NULL);
if (portnode != NULL)
{
- char tempbuffer[20];
-
- /* add the identifying information and attributes */
- xml_set_attribute(portnode, "tag", get_port_tag(port, tempbuffer));
- xml_set_attribute(portnode, "type", input_field_type_to_token(machine, field->type, field->player));
- xml_set_attribute_int(portnode, "mask", field->mask);
- xml_set_attribute_int(portnode, "defvalue", field->defvalue & field->mask);
-
- /* add sequences if changed */
- for (seqtype = 0; seqtype < ARRAY_LENGTH(field->state->seq); seqtype++)
- if (field->state->seq[seqtype] != field->seq[seqtype])
- save_sequence(machine, portnode, seqtype, field->type, field->state->seq[seqtype]);
-
- /* write out non-analog changes */
- if (field->state->analog == NULL)
+ // add the identifying information and attributes
+ astring tempstr;
+ xml_set_attribute(portnode, "tag", port->tag());
+ xml_set_attribute(portnode, "type", input_type_to_token(tempstr, field->type(), field->player()));
+ xml_set_attribute_int(portnode, "mask", field->mask());
+ xml_set_attribute_int(portnode, "defvalue", field->defvalue() & field->mask());
+
+ // add sequences if changed
+ for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++)
+ if (field->live().seq[seqtype] != field->seq(seqtype))
+ save_sequence(portnode, seqtype, field->type(), field->live().seq[seqtype]);
+
+ // write out non-analog changes
+ if (field->live().analog == NULL)
{
- if ((field->state->value & field->mask) != (field->defvalue & field->mask))
- xml_set_attribute_int(portnode, "value", field->state->value & field->mask);
+ if ((field->live().value & field->mask()) != (field->defvalue() & field->mask()))
+ xml_set_attribute_int(portnode, "value", field->live().value & field->mask());
}
- /* write out analog changes */
+ // write out analog changes
else
{
- if (field->state->analog->delta != field->delta)
- xml_set_attribute_int(portnode, "keydelta", field->state->analog->delta);
- if (field->state->analog->centerdelta != field->centerdelta)
- xml_set_attribute_int(portnode, "centerdelta", field->state->analog->centerdelta);
- if (field->state->analog->sensitivity != field->sensitivity)
- xml_set_attribute_int(portnode, "sensitivity", field->state->analog->sensitivity);
- if (field->state->analog->reverse != ((field->flags & ANALOG_FLAG_REVERSE) != 0))
- xml_set_attribute(portnode, "reverse", field->state->analog->reverse ? "yes" : "no");
+ if (field->live().analog->m_delta != field->delta())
+ xml_set_attribute_int(portnode, "keydelta", field->live().analog->m_delta);
+ if (field->live().analog->m_centerdelta != field->centerdelta())
+ xml_set_attribute_int(portnode, "centerdelta", field->live().analog->m_centerdelta);
+ if (field->live().analog->m_sensitivity != field->sensitivity())
+ xml_set_attribute_int(portnode, "sensitivity", field->live().analog->m_sensitivity);
+ if (field->live().analog->m_reverse != field->analog_reverse())
+ xml_set_attribute(portnode, "reverse", field->live().analog->m_reverse ? "yes" : "no");
}
}
}
@@ -3510,311 +3378,212 @@ static void save_game_inputs(running_machine &machine, xml_data_node *parentnode
-/***************************************************************************
- INPUT PLAYBACK
-***************************************************************************/
+//**************************************************************************
+// INPUT PLAYBACK
+//**************************************************************************
-/*-------------------------------------------------
- playback_read_uint8 - read an 8-bit value
- from the playback file
--------------------------------------------------*/
+//-------------------------------------------------
+// playback_read - read a value from the playback
+// file
+//-------------------------------------------------
-static UINT8 playback_read_uint8(running_machine &machine)
+template<typename _Type>
+_Type ioport_manager::playback_read(_Type &result)
{
- ioport_manager &portdata = machine.ioport();
- UINT8 result;
+ // protect against NULL handles if previous reads fail
+ if (!m_playback_file.is_open())
+ result = 0;
- /* protect against NULL handles if previous reads fail */
- if (portdata.playback_file == NULL)
- return 0;
-
- /* read the value; if we fail, end playback */
- if (portdata.playback_file->read(&result, sizeof(result)) != sizeof(result))
+ // read the value; if we fail, end playback
+ else if (m_playback_file.read(&result, sizeof(result)) != sizeof(result))
{
- playback_end(machine, "End of file");
- return 0;
+ playback_end("End of file");
+ result = 0;
}
- /* return the appropriate value */
+ // return the appropriate value
+ else if (sizeof(result) == 8)
+ result = LITTLE_ENDIANIZE_INT64(result);
+ else if (sizeof(result) == 4)
+ result = LITTLE_ENDIANIZE_INT32(result);
+ else if (sizeof(result) == 2)
+ result = LITTLE_ENDIANIZE_INT16(result);
return result;
}
-
-/*-------------------------------------------------
- playback_read_uint32 - read a 32-bit value
- from the playback file
--------------------------------------------------*/
-
-static UINT32 playback_read_uint32(running_machine &machine)
-{
- ioport_manager &portdata = machine.ioport();
- UINT32 result;
-
- /* protect against NULL handles if previous reads fail */
- if (portdata.playback_file == NULL)
- return 0;
-
- /* read the value; if we fail, end playback */
- if (portdata.playback_file->read(&result, sizeof(result)) != sizeof(result))
- {
- playback_end(machine, "End of file");
- return 0;
- }
-
- /* return the appropriate value */
- return LITTLE_ENDIANIZE_INT32(result);
-}
-
-
-/*-------------------------------------------------
- playback_read_uint64 - read a 64-bit value
- from the playback file
--------------------------------------------------*/
-
-static UINT64 playback_read_uint64(running_machine &machine)
+template<>
+bool ioport_manager::playback_read<bool>(bool &result)
{
- ioport_manager &portdata = machine.ioport();
- UINT64 result;
-
- /* protect against NULL handles if previous reads fail */
- if (portdata.playback_file == NULL)
- return 0;
-
- /* read the value; if we fail, end playback */
- if (portdata.playback_file->read(&result, sizeof(result)) != sizeof(result))
- {
- playback_end(machine, "End of file");
- return 0;
- }
-
- /* return the appropriate value */
- return LITTLE_ENDIANIZE_INT64(result);
+ UINT8 temp;
+ playback_read(temp);
+ return result = bool(temp);
}
-/*-------------------------------------------------
- playback_init - initialize INP playback
--------------------------------------------------*/
+//-------------------------------------------------
+// playback_init - initialize INP playback
+//-------------------------------------------------
-static time_t playback_init(running_machine &machine)
+time_t ioport_manager::playback_init()
{
- const char *filename = machine.options().playback();
- ioport_manager &portdata = machine.ioport();
- UINT8 header[INP_HEADER_SIZE];
- time_t basetime;
-
- /* if no file, nothing to do */
+ // if no file, nothing to do
+ const char *filename = machine().options().playback();
if (filename[0] == 0)
return 0;
- /* open the playback file */
- portdata.playback_file = auto_alloc(machine, emu_file(machine.options().input_directory(), OPEN_FLAG_READ));
- file_error filerr = portdata.playback_file->open(filename);
+ // open the playback file
+ file_error filerr = m_playback_file.open(filename);
assert_always(filerr == FILERR_NONE, "Failed to open file for playback");
- /* read the header and verify that it is a modern version; if not, print an error */
- if (portdata.playback_file->read(header, sizeof(header)) != sizeof(header))
+ // read the header and verify that it is a modern version; if not, print an error
+ UINT8 header[INP_HEADER_SIZE];
+ if (m_playback_file.read(header, sizeof(header)) != sizeof(header))
fatalerror("Input file is corrupt or invalid (missing header)");
if (memcmp(header, "MAMEINP\0", 8) != 0)
fatalerror("Input file invalid or in an older, unsupported format");
if (header[0x10] != INP_HEADER_MAJVERSION)
fatalerror("Input file format version mismatch");
- /* output info to console */
+ // output info to console
mame_printf_info("Input file: %s\n", filename);
mame_printf_info("INP version %d.%d\n", header[0x10], header[0x11]);
- basetime = header[0x08] | (header[0x09] << 8) | (header[0x0a] << 16) | (header[0x0b] << 24) |
- ((UINT64)header[0x0c] << 32) | ((UINT64)header[0x0d] << 40) | ((UINT64)header[0x0e] << 48) | ((UINT64)header[0x0f] << 56);
+ time_t basetime = header[0x08] | (header[0x09] << 8) | (header[0x0a] << 16) | (header[0x0b] << 24) |
+ ((UINT64)header[0x0c] << 32) | ((UINT64)header[0x0d] << 40) | ((UINT64)header[0x0e] << 48) | ((UINT64)header[0x0f] << 56);
mame_printf_info("Created %s", ctime(&basetime));
mame_printf_info("Recorded using %s\n", header + 0x20);
- /* verify the header against the current game */
- if (memcmp(machine.system().name, header + 0x14, strlen(machine.system().name) + 1) != 0)
- mame_printf_info("Input file is for %s '%s', not for current %s '%s'\n", emulator_info::get_gamenoun(), header + 0x14, emulator_info::get_gamenoun(), machine.system().name);
-
- /* enable compression */
- portdata.playback_file->compress(FCOMPRESS_MEDIUM);
+ // verify the header against the current game
+ if (memcmp(machine().system().name, header + 0x14, strlen(machine().system().name) + 1) != 0)
+ mame_printf_info("Input file is for %s '%s', not for current %s '%s'\n", emulator_info::get_gamenoun(), header + 0x14, emulator_info::get_gamenoun(), machine().system().name);
+ // enable compression
+ m_playback_file.compress(FCOMPRESS_MEDIUM);
return basetime;
}
-/*-------------------------------------------------
- playback_end - end INP playback
--------------------------------------------------*/
+//-------------------------------------------------
+// playback_end - end INP playback
+//-------------------------------------------------
-static void playback_end(running_machine &machine, const char *message)
+void ioport_manager::playback_end(const char *message)
{
- ioport_manager &portdata = machine.ioport();
-
- /* only applies if we have a live file */
- if (portdata.playback_file != NULL)
+ // only applies if we have a live file
+ if (m_playback_file.is_open())
{
- /* close the file */
- auto_free(machine, portdata.playback_file);
- portdata.playback_file = NULL;
+ // close the file
+ m_playback_file.close();
- /* pop a message */
+ // pop a message
if (message != NULL)
popmessage("Playback Ended\nReason: %s", message);
- /* display speed stats */
- portdata.playback_accumulated_speed /= portdata.playback_accumulated_frames;
- mame_printf_info("Total playback frames: %d\n", (UINT32)portdata.playback_accumulated_frames);
- mame_printf_info("Average recorded speed: %d%%\n", (UINT32)((portdata.playback_accumulated_speed * 200 + 1) >> 21));
+ // display speed stats
+ m_playback_accumulated_speed /= m_playback_accumulated_frames;
+ mame_printf_info("Total playback frames: %d\n", UINT32(m_playback_accumulated_frames));
+ mame_printf_info("Average recorded speed: %d%%\n", UINT32((m_playback_accumulated_speed * 200 + 1) >> 21));
}
}
-/*-------------------------------------------------
- playback_frame - start of frame callback for
- playback
--------------------------------------------------*/
+//-------------------------------------------------
+// playback_frame - start of frame callback for
+// playback
+//-------------------------------------------------
-static void playback_frame(running_machine &machine, attotime curtime)
+void ioport_manager::playback_frame(attotime curtime)
{
- ioport_manager &portdata = machine.ioport();
-
- /* if playing back, fetch the information and verify */
- if (portdata.playback_file != NULL)
+ // if playing back, fetch the information and verify
+ if (m_playback_file.is_open())
{
+ // first the absolute time
attotime readtime;
-
- /* first the absolute time */
- readtime.seconds = playback_read_uint32(machine);
- readtime.attoseconds = playback_read_uint64(machine);
+ playback_read(readtime.seconds);
+ playback_read(readtime.attoseconds);
if (readtime != curtime)
- playback_end(machine, "Out of sync");
+ playback_end("Out of sync");
- /* then the speed */
- portdata.playback_accumulated_speed += playback_read_uint32(machine);
- portdata.playback_accumulated_frames++;
+ // then the speed
+ UINT32 curspeed;
+ m_playback_accumulated_speed += playback_read(curspeed);
+ m_playback_accumulated_frames++;
}
}
-/*-------------------------------------------------
- playback_port - per-port callback for playback
--------------------------------------------------*/
+//-------------------------------------------------
+// playback_port - per-port callback for playback
+//-------------------------------------------------
-static void playback_port(const input_port_config *port)
+void ioport_manager::playback_port(ioport_port &port)
{
- ioport_manager &portdata = port->machine().ioport();
-
- /* if playing back, fetch information about this port */
- if (portdata.playback_file != NULL)
+ // if playing back, fetch information about this port
+ if (m_playback_file.is_open())
{
- analog_field_state *analog;
-
- /* read the default value and the digital state */
- port->state->defvalue = playback_read_uint32(port->machine());
- port->state->digital = playback_read_uint32(port->machine());
+ // read the default value and the digital state
+ playback_read(port.live().defvalue);
+ playback_read(port.live().digital);
- /* loop over analog ports and save their data */
- for (analog = port->state->analoglist; analog != NULL; analog = analog->next)
+ // loop over analog ports and save their data
+ for (analog_field *analog = port.live().analoglist.first(); analog != NULL; analog = analog->next())
{
- /* read current and previous values */
- analog->accum = playback_read_uint32(port->machine());
- analog->previous = playback_read_uint32(port->machine());
+ // read current and previous values
+ playback_read(analog->m_accum);
+ playback_read(analog->m_previous);
- /* read configuration information */
- analog->sensitivity = playback_read_uint32(port->machine());
- analog->reverse = playback_read_uint8(port->machine());
+ // read configuration information
+ playback_read(analog->m_sensitivity);
+ playback_read(analog->m_reverse);
}
}
}
+//-------------------------------------------------
+// record_write - write a value to the record file
+//-------------------------------------------------
-/***************************************************************************
- INPUT RECORDING
-***************************************************************************/
-
-/*-------------------------------------------------
- record_write_uint8 - write an 8-bit value
- to the record file
--------------------------------------------------*/
-
-static void record_write_uint8(running_machine &machine, UINT8 data)
+template<typename _Type>
+void ioport_manager::record_write(_Type value)
{
- ioport_manager &portdata = machine.ioport();
- UINT8 result = data;
-
- /* protect against NULL handles if previous reads fail */
- if (portdata.record_file == NULL)
- return;
-
- /* read the value; if we fail, end playback */
- if (portdata.record_file->write(&result, sizeof(result)) != sizeof(result))
- record_end(machine, "Out of space");
-}
-
-
-/*-------------------------------------------------
- record_write_uint32 - write a 32-bit value
- to the record file
--------------------------------------------------*/
-
-static void record_write_uint32(running_machine &machine, UINT32 data)
-{
- ioport_manager &portdata = machine.ioport();
- UINT32 result = LITTLE_ENDIANIZE_INT32(data);
-
- /* protect against NULL handles if previous reads fail */
- if (portdata.record_file == NULL)
+ // protect against NULL handles if previous reads fail
+ if (!m_record_file.is_open())
return;
- /* read the value; if we fail, end playback */
- if (portdata.record_file->write(&result, sizeof(result)) != sizeof(result))
- record_end(machine, "Out of space");
+ // read the value; if we fail, end playback
+ if (m_record_file.write(&value, sizeof(value)) != sizeof(value))
+ record_end("Out of space");
}
-
-/*-------------------------------------------------
- record_write_uint64 - write a 64-bit value
- to the record file
--------------------------------------------------*/
-
-static void record_write_uint64(running_machine &machine, UINT64 data)
+template<>
+void ioport_manager::record_write<bool>(bool value)
{
- ioport_manager &portdata = machine.ioport();
- UINT64 result = LITTLE_ENDIANIZE_INT64(data);
-
- /* protect against NULL handles if previous reads fail */
- if (portdata.record_file == NULL)
- return;
-
- /* read the value; if we fail, end playback */
- if (portdata.record_file->write(&result, sizeof(result)) != sizeof(result))
- record_end(machine, "Out of space");
+ UINT8 byte = UINT8(value);
+ record_write(byte);
}
-/*-------------------------------------------------
- record_init - initialize INP recording
--------------------------------------------------*/
+//-------------------------------------------------
+// record_init - initialize INP recording
+//-------------------------------------------------
-static void record_init(running_machine &machine)
+void ioport_manager::record_init()
{
- const char *filename = machine.options().record();
- ioport_manager &portdata = machine.ioport();
- UINT8 header[INP_HEADER_SIZE];
- system_time systime;
-
- /* if no file, nothing to do */
+ // if no file, nothing to do
+ const char *filename = machine().options().record();
if (filename[0] == 0)
return;
- /* open the record file */
- portdata.record_file = auto_alloc(machine, emu_file(machine.options().input_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS));
- file_error filerr = portdata.record_file->open(filename);
+ // open the record file
+ file_error filerr = m_record_file.open(filename);
assert_always(filerr == FILERR_NONE, "Failed to open file for recording");
- /* get the base time */
- machine.base_datetime(systime);
+ // get the base time
+ system_time systime;
+ machine().base_datetime(systime);
- /* fill in the header */
- memset(header, 0, sizeof(header));
+ // fill in the header
+ UINT8 header[INP_HEADER_SIZE] = { 0 };
memcpy(header, "MAMEINP\0", 8);
header[0x08] = systime.time >> 0;
header[0x09] = systime.time >> 8;
@@ -3826,1042 +3595,922 @@ static void record_init(running_machine &machine)
header[0x0f] = systime.time >> 56;
header[0x10] = INP_HEADER_MAJVERSION;
header[0x11] = INP_HEADER_MINVERSION;
- strcpy((char *)header + 0x14, machine.system().name);
+ strcpy((char *)header + 0x14, machine().system().name);
sprintf((char *)header + 0x20, "%s %s", emulator_info::get_appname(), build_version);
- /* write it */
- portdata.record_file->write(header, sizeof(header));
+ // write it
+ m_record_file.write(header, sizeof(header));
- /* enable compression */
- portdata.record_file->compress(FCOMPRESS_MEDIUM);
+ // enable compression
+ m_record_file.compress(FCOMPRESS_MEDIUM);
}
-/*-------------------------------------------------
- record_end - end INP recording
--------------------------------------------------*/
+//-------------------------------------------------
+// record_end - end INP recording
+//-------------------------------------------------
-static void record_end(running_machine &machine, const char *message)
+void ioport_manager::record_end(const char *message)
{
- ioport_manager &portdata = machine.ioport();
-
- /* only applies if we have a live file */
- if (portdata.record_file != NULL)
+ // only applies if we have a live file
+ if (m_record_file.is_open())
{
- /* close the file */
- auto_free(machine, portdata.record_file);
- portdata.record_file = NULL;
+ // close the file
+ m_record_file.close();
- /* pop a message */
+ // pop a message
if (message != NULL)
popmessage("Recording Ended\nReason: %s", message);
}
}
-/*-------------------------------------------------
- record_frame - start of frame callback for
- recording
--------------------------------------------------*/
+//-------------------------------------------------
+// record_frame - start of frame callback for
+// recording
+//-------------------------------------------------
-static void record_frame(running_machine &machine, attotime curtime)
+void ioport_manager::record_frame(attotime curtime)
{
- ioport_manager &portdata = machine.ioport();
-
- /* if recording, record information about the current frame */
- if (portdata.record_file != NULL)
+ // if recording, record information about the current frame
+ if (m_record_file.is_open())
{
- /* first the absolute time */
- record_write_uint32(machine, curtime.seconds);
- record_write_uint64(machine, curtime.attoseconds);
+ // first the absolute time
+ record_write(curtime.seconds);
+ record_write(curtime.attoseconds);
- /* then the current speed */
- record_write_uint32(machine, machine.video().speed_percent() * (double)(1 << 20));
+ // then the current speed
+ record_write(UINT32(machine().video().speed_percent() * double(1 << 20)));
}
}
-/*-------------------------------------------------
- record_port - per-port callback for record
--------------------------------------------------*/
+//-------------------------------------------------
+// record_port - per-port callback for record
+//-------------------------------------------------
-static void record_port(const input_port_config *port)
+void ioport_manager::record_port(ioport_port &port)
{
- ioport_manager &portdata = port->machine().ioport();
-
- /* if recording, store information about this port */
- if (portdata.record_file != NULL)
+ // if recording, store information about this port
+ if (m_record_file.is_open())
{
- analog_field_state *analog;
+ // store the default value and digital state
+ record_write(port.live().defvalue);
+ record_write(port.live().digital);
- /* store the default value and digital state */
- record_write_uint32(port->machine(), port->state->defvalue);
- record_write_uint32(port->machine(), port->state->digital);
-
- /* loop over analog ports and save their data */
- for (analog = port->state->analoglist; analog != NULL; analog = analog->next)
+ // loop over analog ports and save their data
+ for (analog_field *analog = port.live().analoglist.first(); analog != NULL; analog = analog->next())
{
- /* store current and previous values */
- record_write_uint32(port->machine(), analog->accum);
- record_write_uint32(port->machine(), analog->previous);
+ // store current and previous values
+ record_write(analog->m_accum);
+ record_write(analog->m_previous);
- /* store configuration information */
- record_write_uint32(port->machine(), analog->sensitivity);
- record_write_uint8(port->machine(), analog->reverse);
+ // store configuration information
+ record_write(analog->m_sensitivity);
+ record_write(analog->m_reverse);
}
}
}
-int input_machine_has_keyboard(running_machine &machine)
-{
- int have_keyboard = FALSE;
- const input_field_config *field;
- const input_port_config *port;
- for (port = machine.ioport().first_port(); port != NULL; port = port->next())
- {
- for (field = port->first_field(); field != NULL; field = field->next())
- {
- // if we are at init, check IPT_KEYBOARD for inputx_init
- if (!port->machine().ioport().safe_to_read && field->type == IPT_KEYBOARD)
- {
- have_keyboard = TRUE;
- break;
- }
- // else, check if there is a keyboard and if such a keyboard is enabled
- if (field->type == IPT_KEYBOARD && input_condition_true(field->machine(), &field->condition, field->port().owner()))
- {
- have_keyboard = TRUE;
- break;
- }
- }
- }
- return have_keyboard;
-}
-/***************************************************************************
- CODE ASSEMBLING
-***************************************************************************/
+//**************************************************************************
+// I/O PORT CONFIGURER
+//**************************************************************************
-/*-------------------------------------------------
- code_point_string - obtain a string representation of a
- given code; used for logging and debugging
--------------------------------------------------*/
+//-------------------------------------------------
+// ioport_configurer - constructor
+//-------------------------------------------------
-static const char *code_point_string(running_machine &machine, unicode_char ch)
+ioport_configurer::ioport_configurer(device_t &owner, ioport_list &portlist, astring &errorbuf)
+ : m_owner(owner),
+ m_portlist(portlist),
+ m_errorbuf(errorbuf),
+ m_curport(NULL),
+ m_curfield(NULL),
+ m_cursetting(NULL)
{
- static char buf[16];
- const char *result = buf;
-
- switch(ch)
- {
- /* check some magic values */
- case '\0': strcpy(buf, "\\0"); break;
- case '\r': strcpy(buf, "\\r"); break;
- case '\n': strcpy(buf, "\\n"); break;
- case '\t': strcpy(buf, "\\t"); break;
-
- default:
- if ((ch >= 32) && (ch < 128))
- {
- /* seven bit ASCII is easy */
- buf[0] = (char) ch;
- buf[1] = '\0';
- }
- else if (ch >= UCHAR_MAMEKEY_BEGIN)
- {
- /* try to obtain a codename with code_name(); this can result in an empty string */
- input_code code(DEVICE_CLASS_KEYBOARD, 0, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, input_item_id(ch - UCHAR_MAMEKEY_BEGIN));
- astring tempstr;
- snprintf(buf, ARRAY_LENGTH(buf), "%s", machine.input().code_name(tempstr, code));
- }
- else
- {
- /* empty string; resolve later */
- buf[0] = '\0';
- }
-
- /* did we fail to resolve? if so, we have a last resort */
- if (buf[0] == '\0')
- snprintf(buf, ARRAY_LENGTH(buf), "U+%04X", (unsigned) ch);
- break;
- }
- return result;
}
-/*-------------------------------------------------
- scan_keys - scans through input ports and
- sets up natural keyboard input mapping
--------------------------------------------------*/
+//-------------------------------------------------
+// string_from_token - convert an
+// ioport_token to a default string
+//-------------------------------------------------
-static int scan_keys(running_machine &machine, const input_port_config *portconfig, inputx_code *codes, const input_port_config * *ports, const input_field_config * *shift_ports, int keys, int shift)
+const char *ioport_configurer::string_from_token(const char *string)
{
- int code_count = 0;
- const input_port_config *port;
- const input_field_config *field;
- unicode_char code;
+ // 0 is an invalid index
+ if (string == NULL)
+ return NULL;
+
+ // if the index is greater than the count, assume it to be a pointer
+ if (FPTR(string) >= INPUT_STRING_COUNT)
+ return string;
- assert(keys < NUM_SIMUL_KEYS);
+#if FALSE // Set TRUE, If you want to take care missing-token or wrong-sorting
- for (port = portconfig; port != NULL; port = port->next())
+ // otherwise, scan the list for a matching string and return it
{
- for (field = port->first_field(); field != NULL; field = field->next())
- {
- if (field->type == IPT_KEYBOARD)
- {
- code = get_keyboard_code(field, shift);
- if (code != 0)
- {
- /* is this a shifter key? */
- if ((code >= UCHAR_SHIFT_BEGIN) && (code <= UCHAR_SHIFT_END))
- {
- shift_ports[keys] = field;
- code_count += scan_keys(machine,
- portconfig,
- codes ? &codes[code_count] : NULL,
- ports,
- shift_ports,
- keys+1,
- code - UCHAR_SHIFT_1 + 1);
- }
- else
- {
- /* not a shifter key; record normally */
- if (codes)
- {
- /* if we have a destination, record the codes used here */
- memcpy((void *) codes[code_count].field, shift_ports, sizeof(shift_ports[0]) * keys);
- codes[code_count].ch = code;
- codes[code_count].field[keys] = field;
- }
+ int index;
+ for (index = 0; index < ARRAY_LENGTH(input_port_default_strings); index++)
+ if (input_port_default_strings[index].id == FPTR(string))
+ return input_port_default_strings[index].string;
+ }
+ return "(Unknown Default)";
- /* increment the count */
- code_count++;
+#else
- if (LOG_INPUTX)
- logerror("inputx: code=%i (%s) port=%p field->name='%s'\n", (int) code, code_point_string(machine, code), port, field->name);
- }
- }
- }
- }
- }
- return code_count;
-}
+ return input_port_default_strings[FPTR(string)-1].string;
+#endif
+}
-/*-------------------------------------------------
- build_codes - given an input port table, create
- a input code table useful for mapping unicode
- chars
--------------------------------------------------*/
+//-------------------------------------------------
+// port_alloc - allocate a new port
+//-------------------------------------------------
-static inputx_code *build_codes(running_machine &machine, const input_port_config *portconfig)
+void ioport_configurer::port_alloc(const char *tag)
{
- inputx_code *codes = NULL;
- const input_port_config *ports[NUM_SIMUL_KEYS];
- const input_field_config *fields[NUM_SIMUL_KEYS];
- int code_count;
+ // create the full tag
+ astring fulltag;
+ m_owner.subtag(fulltag, tag);
+
+ // add it to the list, and reset current field/setting
+ m_curport = &m_portlist.append(fulltag, *global_alloc(ioport_port(m_owner, fulltag)));
+ m_curfield = NULL;
+ m_cursetting = NULL;
+}
- /* first count the number of codes */
- code_count = scan_keys(machine, portconfig, NULL, ports, fields, 0, 0);
- if (code_count > 0)
- {
- /* allocate the codes */
- codes = auto_alloc_array_clear(machine, inputx_code, code_count + 1);
- /* and populate them */
- scan_keys(machine, portconfig, codes, ports, fields, 0, 0);
- }
- return codes;
-}
+//-------------------------------------------------
+// port_modify - find an existing port and
+// modify it
+//-------------------------------------------------
+void ioport_configurer::port_modify(const char *tag)
+{
+ // create the full tag
+ astring fulltag;
+ m_owner.subtag(fulltag, tag);
+ // find the existing port
+ m_curport = m_portlist.find(fulltag.cstr());
+ if (m_curport == NULL)
+ throw emu_fatalerror("Requested to modify nonexistent port '%s'", fulltag.cstr());
+
+ // bump the modification count, and reset current field/setting
+ m_curport->m_modcount++;
+ m_curfield = NULL;
+ m_cursetting = NULL;
+}
-/***************************************************************************
- VALIDITY CHECKS
-***************************************************************************/
-/*-------------------------------------------------
- validate_natural_keyboard_statics -
- validates natural keyboard static data
--------------------------------------------------*/
+//-------------------------------------------------
+// field_alloc - allocate a new field
+//-------------------------------------------------
-int validate_natural_keyboard_statics(void)
+void ioport_configurer::field_alloc(ioport_type type, ioport_value defval, ioport_value mask, const char *name)
{
- int i;
- int error = FALSE;
- unicode_char last_char = 0;
- const char_info *ci;
+ // make sure we have a port
+ if (m_curport == NULL)
+ throw emu_fatalerror("alloc_field called with no active port (mask=%X defval=%X)\n", mask, defval); \
- /* check to make sure that charinfo is in order */
- for (i = 0; i < ARRAY_LENGTH(charinfo); i++)
- {
- if (last_char >= charinfo[i].ch)
- {
- mame_printf_error("inputx: charinfo is out of order; 0x%08x should be higher than 0x%08x\n", charinfo[i].ch, last_char);
- error = TRUE;
- }
- last_char = charinfo[i].ch;
- }
+ // append the field
+ if (type != IPT_UNKNOWN && type != IPT_UNUSED)
+ m_curport->m_active |= mask;
+ m_curfield = &m_curport->m_fieldlist.append(*global_alloc(ioport_field(*m_curport, type, defval, mask, string_from_token(name))));
- /* check to make sure that I can look up everything on alternate_charmap */
- for (i = 0; i < ARRAY_LENGTH(charinfo); i++)
- {
- ci = find_charinfo(charinfo[i].ch);
- if (ci != &charinfo[i])
- {
- mame_printf_error("inputx: expected find_charinfo(0x%08x) to work properly\n", charinfo[i].ch);
- error = TRUE;
- }
- }
- return error;
+ // reset the current setting
+ m_cursetting = NULL;
}
+//-------------------------------------------------
+// field_add_char - add a character to a field
+//-------------------------------------------------
-/***************************************************************************
- CORE IMPLEMENTATION
-***************************************************************************/
-
-static void clear_keybuffer(running_machine &machine)
+void ioport_configurer::field_add_char(unicode_char ch)
{
- ioport_manager &portdata = machine.ioport();
- portdata.keybuffer.buffer = NULL;
- portdata.queue_chars = NULL;
- portdata.codes = NULL;
+ for (int index = 0; index < ARRAY_LENGTH(m_curfield->m_chars); index++)
+ if (m_curfield->m_chars[index] == 0)
+ {
+ m_curfield->m_chars[index] = ch;
+ break;
+ }
}
+//-------------------------------------------------
+// field_add_code - add a character to a field
+//-------------------------------------------------
-static void setup_keybuffer(running_machine &machine)
+void ioport_configurer::field_add_code(input_seq_type which, input_code code)
{
- ioport_manager &portdata = machine.ioport();
- portdata.inputx_timer = machine.scheduler().timer_alloc(FUNC(inputx_timerproc));
- portdata.keybuffer.begin_pos = 0;
- portdata.keybuffer.end_pos = 0;
- portdata.keybuffer.status_keydown = 0;
- portdata.keybuffer.size = KEY_BUFFER_SIZE;
- portdata.keybuffer.buffer = auto_alloc_array(machine, unicode_char, portdata.keybuffer.size);
- machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(clear_keybuffer), &machine));
+ m_curfield->m_seq[which] |= code;
}
+//-------------------------------------------------
+// setting_alloc - allocate a new setting
+//-------------------------------------------------
-void inputx_init(running_machine &machine)
+void ioport_configurer::setting_alloc(ioport_value value, const char *name)
{
- ioport_manager &portdata = machine.ioport();
- portdata.inputx_timer = NULL;
- portdata.accept_char = NULL;
- portdata.charqueue_empty = NULL;
- clear_keybuffer(machine);
+ // make sure we have a field
+ if (m_curfield == NULL)
+ throw emu_fatalerror("alloc_setting called with no active field (value=%X name=%s)\n", value, name);
- if (machine.debug_flags & DEBUG_FLAG_ENABLED)
- {
- debug_console_register_command(machine, "input", CMDFLAG_NONE, 0, 1, 1, execute_input);
- debug_console_register_command(machine, "dumpkbd", CMDFLAG_NONE, 0, 0, 1, execute_dumpkbd);
- }
-
- /* posting keys directly only makes sense for a computer */
- if (input_machine_has_keyboard(machine))
- {
- portdata.codes = build_codes(machine, machine.ioport().first_port());
- setup_keybuffer(machine);
- }
+ // append a new setting
+ m_curfield->m_settinglist.append(*global_alloc(ioport_setting(*m_curfield, value & m_curfield->mask(), string_from_token(name))));
}
+//-------------------------------------------------
+// set_condition - set the condition for either
+// the current setting or field
+//-------------------------------------------------
-void inputx_setup_natural_keyboard(
- running_machine &machine,
- int (*queue_chars)(running_machine &machine, const unicode_char *text, size_t text_len),
- int (*accept_char)(running_machine &machine, unicode_char ch),
- int (*charqueue_empty)(running_machine &machine))
+void ioport_configurer::set_condition(ioport_condition::condition_t condition, const char *tag, ioport_value mask, ioport_value value)
{
- ioport_manager &portdata = machine.ioport();
- portdata.queue_chars = queue_chars;
- portdata.accept_char = accept_char;
- portdata.charqueue_empty = charqueue_empty;
+ ioport_condition &target = (m_cursetting != NULL) ? m_cursetting->condition() : m_curfield->condition();
+ target.set(condition, tag, mask, value);
}
-int inputx_can_post(running_machine &machine)
-{
- ioport_manager &portdata = machine.ioport();
- return portdata.queue_chars || portdata.codes;
-}
+//-------------------------------------------------
+// onoff_alloc - allocate an on/off DIP switch
+//-------------------------------------------------
-static int can_post_key_directly(running_machine &machine, unicode_char ch)
+void ioport_configurer::onoff_alloc(const char *name, ioport_value defval, ioport_value mask, const char *diplocation)
{
- ioport_manager &portdata = machine.ioport();
- int rc = FALSE;
- const inputx_code *code;
+ // allocate a field normally
+ field_alloc(IPT_DIPSWITCH, defval, mask, name);
- if (portdata.queue_chars)
- {
- rc = portdata.accept_char ? (*portdata.accept_char)(machine, ch) : TRUE;
- }
- else
+ // special case service mode
+ if (name == DEF_STR(Service_Mode))
{
- code = find_code(portdata.codes, ch);
- if (code)
- rc = code->field[0] != NULL;
+ field_set_toggle();
+ m_curfield->m_seq[SEQ_TYPE_STANDARD].set(KEYCODE_F2);
}
- return rc;
+
+ // expand the diplocation
+ if (diplocation != NULL)
+ field_set_diplocation(diplocation);
+
+ // allocate settings
+ setting_alloc(defval & mask, DEF_STR(Off));
+ setting_alloc(~defval & mask, DEF_STR(On));
}
-static int can_post_key_alternate(running_machine &machine, unicode_char ch)
-{
- const char *s;
- const char_info *ci;
- unicode_char uchar;
- int rc;
+/***************************************************************************
+ MISCELLANEOUS
+***************************************************************************/
- ci = find_charinfo(ch);
- s = ci ? ci->alternate : NULL;
- if (!s)
- return 0;
+//-------------------------------------------------
+// find - look up information about a particular
+// character
+//-------------------------------------------------
- while(*s)
+const char_info *char_info::find(unicode_char target)
+{
+ // perform a simple binary search to find the proper alternate
+ int low = 0;
+ int high = ARRAY_LENGTH(charinfo);
+ while (high > low)
{
- rc = uchar_from_utf8(&uchar, s, strlen(s));
- if (rc <= 0)
- return 0;
- if (!can_post_key_directly(machine, uchar))
- return 0;
- s += rc;
+ int middle = (high + low) / 2;
+ unicode_char ch = charinfo[middle].ch;
+ if (ch < target)
+ low = middle + 1;
+ else if (ch > target)
+ high = middle;
+ else
+ return &charinfo[middle];
}
- return 1;
+ return NULL;
}
-static attotime choose_delay(ioport_manager &portdata, unicode_char ch)
-{
- if (portdata.current_rate != attotime::zero)
- return portdata.current_rate;
- attotime delay = attotime::zero;
- if (portdata.queue_chars)
- {
- /* systems with queue_chars can afford a much smaller delay */
- delay = attotime::from_msec(10);
- }
- else
- {
- switch(ch) {
- case '\r':
- delay = attotime::from_msec(200);
- break;
+//-------------------------------------------------
+// dynamic_field - constructor
+//-------------------------------------------------
- default:
- delay = attotime::from_msec(50);
- break;
- }
- }
- return delay;
+dynamic_field::dynamic_field(ioport_field &field)
+ : m_next(NULL),
+ m_field(field),
+ m_shift(0),
+ m_oldval(field.defvalue())
+{
+ // fill in the data
+ for (ioport_value mask = field.mask(); !(mask & 1); mask >>= 1)
+ m_shift++;
+ m_oldval >>= m_shift;
}
+//-------------------------------------------------
+// read - read the updated value and merge it
+// into the target
+//-------------------------------------------------
-static void internal_post_key(running_machine &machine, unicode_char ch)
+void dynamic_field::read(ioport_value &result)
{
- ioport_manager &portdata = machine.ioport();
- key_buffer *keybuf;
+ // skip if not enabled
+ if (!m_field.enabled())
+ return;
+
+ // call the callback to read a new value
+ ioport_value newval = m_field.m_read(m_field, m_field.m_read_param);
+ m_oldval = newval;
+
+ // merge in the bits (don't invert yet, as all digitals are inverted together)
+ result = (result & ~m_field.mask()) | ((newval << m_shift) & m_field.mask());
+}
- keybuf = get_buffer(machine);
- /* need to start up the timer? */
- if (keybuf->begin_pos == keybuf->end_pos)
- {
- portdata.inputx_timer->adjust(choose_delay(portdata, ch));
- keybuf->status_keydown = 0;
- }
+//-------------------------------------------------
+// write - track a change to a value and call
+// the write callback if there's something new
+//-------------------------------------------------
+
+void dynamic_field::write(ioport_value newval)
+{
+ // skip if not enabled
+ if (!m_field.enabled())
+ return;
- keybuf->buffer[keybuf->end_pos++] = ch;
- if ((keybuf->end_pos+1) % keybuf->size == keybuf->begin_pos)
+ // if the bits have changed, call the handler
+ newval = ((newval ^ m_field.defvalue()) & m_field.mask()) >> m_shift;
+ if (m_oldval != newval)
{
- // Buffer full
- unicode_char *old_buffer = keybuf->buffer;
- keybuf->size = keybuf->size + KEY_BUFFER_SIZE;
- keybuf->buffer = auto_alloc_array(machine, unicode_char, keybuf->size);
- for( int i = keybuf->begin_pos; i <= keybuf->end_pos; i++ )
- {
- keybuf->buffer[i] = old_buffer[i];
- }
- auto_free(machine, old_buffer);
+ m_field.m_write(m_field, m_field.m_write_param, m_oldval, newval);
+ m_oldval = newval;
}
- keybuf->end_pos %= keybuf->size;
}
+//-------------------------------------------------
+// analog_field - constructor
+//-------------------------------------------------
-static int buffer_full(running_machine &machine)
-{
- key_buffer *keybuf;
- keybuf = get_buffer(machine);
- return ((keybuf->end_pos + 1) % keybuf->size) == keybuf->begin_pos;
-}
+analog_field::analog_field(ioport_field &field)
+ : m_next(NULL),
+ m_field(field),
+ m_shift(0),
+ m_adjdefvalue(field.defvalue() & field.mask()),
+ m_adjmin(field.minval() & field.mask()),
+ m_adjmax(field.maxval() & field.mask()),
+ m_sensitivity(field.sensitivity()),
+ m_reverse(field.analog_reverse()),
+ m_delta(field.delta()),
+ m_centerdelta(field.centerdelta()),
+ m_accum(0),
+ m_previous(0),
+ m_previousanalog(0),
+ m_minimum(INPUT_ABSOLUTE_MIN),
+ m_maximum(INPUT_ABSOLUTE_MAX),
+ m_center(0),
+ m_reverse_val(0),
+ m_scalepos(0),
+ m_scaleneg(0),
+ m_keyscalepos(0),
+ m_keyscaleneg(0),
+ m_positionalscale(0),
+ m_absolute(false),
+ m_wraps(false),
+ m_autocenter(false),
+ m_single_scale(false),
+ m_interpolate(false),
+ m_lastdigital(false)
+{
+ // compute the shift amount and number of bits
+ for (ioport_value mask = field.mask(); !(mask & 1); mask >>= 1)
+ m_shift++;
+
+ // initialize core data
+ m_adjdefvalue >>= m_shift;
+ m_adjmin >>= m_shift;
+ m_adjmax >>= m_shift;
+
+ // set basic parameters based on the configured type
+ switch (field.type())
+ {
+ // paddles and analog joysticks are absolute and autocenter
+ case IPT_AD_STICK_X:
+ case IPT_AD_STICK_Y:
+ case IPT_AD_STICK_Z:
+ case IPT_PADDLE:
+ case IPT_PADDLE_V:
+ m_absolute = true;
+ m_autocenter = true;
+ m_interpolate = !field.analog_reset();
+ break;
+ // pedals start at and autocenter to the min range
+ case IPT_PEDAL:
+ case IPT_PEDAL2:
+ case IPT_PEDAL3:
+ m_center = INPUT_ABSOLUTE_MIN;
+ m_accum = apply_inverse_sensitivity(m_center);
+ m_absolute = true;
+ m_autocenter = true;
+ m_interpolate = !field.analog_reset();
+ break;
+ // lightguns are absolute as well, but don't autocenter and don't interpolate their values
+ case IPT_LIGHTGUN_X:
+ case IPT_LIGHTGUN_Y:
+ m_absolute = true;
+ m_autocenter = false;
+ m_interpolate = false;
+ break;
-static void inputx_postn_rate(running_machine &machine, const unicode_char *text, size_t text_len, attotime rate)
-{
- ioport_manager &portdata = machine.ioport();
- int last_cr = 0;
- unicode_char ch;
- const char *s;
- const char_info *ci;
- const inputx_code *code;
+ // positional devices are absolute, but can also wrap like relative devices
+ // set each position to be 512 units
+ case IPT_POSITIONAL:
+ case IPT_POSITIONAL_V:
+ m_positionalscale = compute_scale(field.maxval(), INPUT_ABSOLUTE_MAX - INPUT_ABSOLUTE_MIN);
+ m_adjmin = 0;
+ m_adjmax = field.maxval() - 1;
+ m_wraps = field.analog_wraps();
+ m_autocenter = !m_wraps;
+ break;
- portdata.current_rate = rate;
+ // dials, mice and trackballs are relative devices
+ // these have fixed "min" and "max" values based on how many bits are in the port
+ // in addition, we set the wrap around min/max values to 512 * the min/max values
+ // this takes into account the mapping that one mouse unit ~= 512 analog units
+ case IPT_DIAL:
+ case IPT_DIAL_V:
+ case IPT_TRACKBALL_X:
+ case IPT_TRACKBALL_Y:
+ case IPT_MOUSE_X:
+ case IPT_MOUSE_Y:
+ m_absolute = false;
+ m_wraps = true;
+ m_interpolate = !field.analog_reset();
+ break;
+
+ default:
+ fatalerror("Unknown analog port type -- don't know if it is absolute or not");
+ break;
+ }
- if (inputx_can_post(machine))
+ // further processing for absolute controls
+ if (m_absolute)
{
- while((text_len > 0) && !buffer_full(machine))
- {
- ch = *(text++);
- text_len--;
+ // if the default value is pegged at the min or max, use a single scale value for the whole axis
+ m_single_scale = (m_adjdefvalue == m_adjmin) || (m_adjdefvalue == m_adjmax);
- /* change all eolns to '\r' */
- if ((ch != '\n') || !last_cr)
- {
- if (ch == '\n')
- ch = '\r';
- else
- last_cr = (ch == '\r');
+ // if not "single scale", compute separate scales for each side of the default
+ if (!m_single_scale)
+ {
+ // unsigned
+ m_scalepos = compute_scale(m_adjmax - m_adjdefvalue, INPUT_ABSOLUTE_MAX - 0);
+ m_scaleneg = compute_scale(m_adjdefvalue - m_adjmin, 0 - INPUT_ABSOLUTE_MIN);
- if (LOG_INPUTX)
- {
- code = find_code(portdata.codes, ch);
- logerror("inputx_postn(): code=%i (%s) field->name='%s'\n", (int) ch, code_point_string(machine, ch), (code && code->field[0]) ? code->field[0]->name : "<null>");
- }
+ if (m_adjmin > m_adjmax)
+ m_scaleneg = -m_scaleneg;
- if (can_post_key_directly(machine, ch))
- {
- /* we can post this key in the queue directly */
- internal_post_key(machine, ch);
- }
- else if (can_post_key_alternate(machine, ch))
- {
- /* we can post this key with an alternate representation */
- ci = find_charinfo(ch);
- assert(ci && ci->alternate);
- s = ci->alternate;
- while(*s)
- {
- s += uchar_from_utf8(&ch, s, strlen(s));
- internal_post_key(machine, ch);
- }
- }
- }
- else
- {
- last_cr = 0;
- }
+ // reverse point is at center
+ m_reverse_val = 0;
}
- }
-}
-
-
+ else
+ {
+ // single axis that increases from default
+ m_scalepos = compute_scale(m_adjmax - m_adjmin, INPUT_ABSOLUTE_MAX - INPUT_ABSOLUTE_MIN);
-static TIMER_CALLBACK(inputx_timerproc)
-{
- ioport_manager &portdata = machine.ioport();
- key_buffer *keybuf;
- attotime delay;
+ // move from default
+ if (m_adjdefvalue == m_adjmax)
+ m_scalepos = -m_scalepos;
- keybuf = get_buffer(machine);
+ // make the scaling the same for easier coding when we need to scale
+ m_scaleneg = m_scalepos;
- if (portdata.queue_chars)
- {
- /* the driver has a queue_chars handler */
- while((keybuf->begin_pos != keybuf->end_pos) && (*portdata.queue_chars)(machine, &keybuf->buffer[keybuf->begin_pos], 1))
- {
- keybuf->begin_pos++;
- keybuf->begin_pos %= keybuf->size;
-
- if (portdata.current_rate != attotime::zero)
- break;
+ // reverse point is at max
+ m_reverse_val = m_maximum;
}
}
+
+ // relative and positional controls all map directly with a 512x scale factor
else
{
- /* the driver does not have a queue_chars handler */
- if (keybuf->status_keydown)
- {
- keybuf->status_keydown = FALSE;
- keybuf->begin_pos++;
- keybuf->begin_pos %= keybuf->size;
- }
+ // The relative code is set up to allow specifing PORT_MINMAX and default values.
+ // The validity checks are purposely set up to not allow you to use anything other
+ // a default of 0 and PORT_MINMAX(0,mask). This is in case the need arises to use
+ // this feature in the future. Keeping the code in does not hurt anything.
+ if (m_adjmin > m_adjmax)
+ // adjust for signed
+ m_adjmin = -m_adjmin;
+
+ if (m_wraps)
+ m_adjmax++;
+
+ m_minimum = (m_adjmin - m_adjdefvalue) * INPUT_RELATIVE_PER_PIXEL;
+ m_maximum = (m_adjmax - m_adjdefvalue) * INPUT_RELATIVE_PER_PIXEL;
+
+ // make the scaling the same for easier coding when we need to scale
+ m_scaleneg = m_scalepos = compute_scale(1, INPUT_RELATIVE_PER_PIXEL);
+
+ if (m_field.analog_reset())
+ // delta values reverse from center
+ m_reverse_val = 0;
else
{
- keybuf->status_keydown = TRUE;
- }
- }
+ // positional controls reverse from their max range
+ m_reverse_val = m_maximum + m_minimum;
- /* need to make sure timerproc is called again if buffer not empty */
- if (keybuf->begin_pos != keybuf->end_pos)
- {
- delay = choose_delay(portdata, keybuf->buffer[keybuf->begin_pos]);
- portdata.inputx_timer->adjust(delay);
+ // relative controls reverse from 1 past their max range
+ if (m_wraps)
+ m_reverse_val -= INPUT_RELATIVE_PER_PIXEL;
+ }
}
-}
-int inputx_is_posting(running_machine &machine)
-{
- ioport_manager &portdata = machine.ioport();
- const key_buffer *keybuf;
- keybuf = get_buffer(machine);
- return (keybuf->begin_pos != keybuf->end_pos) || (portdata.charqueue_empty && !(*portdata.charqueue_empty)(machine));
+ // compute scale for keypresses
+ m_keyscalepos = recip_scale(m_scalepos);
+ m_keyscaleneg = recip_scale(m_scaleneg);
}
-/***************************************************************************
- Coded input
+//-------------------------------------------------
+// apply_min_max - clamp the given input value to
+// the appropriate min/max for the analog control
+//-------------------------------------------------
-***************************************************************************/
-static void inputx_postc_rate(running_machine &machine, unicode_char ch, attotime rate);
-
-static void inputx_postn_coded_rate(running_machine &machine, const char *text, size_t text_len, attotime rate)
+inline ioport_value analog_field::apply_min_max(ioport_value value) const
{
- size_t i, j, key_len, increment;
- unicode_char ch;
+ // take the analog minimum and maximum values and apply the inverse of the
+ // sensitivity so that we can clamp against them before applying sensitivity
+ INT32 adjmin = apply_inverse_sensitivity(m_minimum);
+ INT32 adjmax = apply_inverse_sensitivity(m_maximum);
- static const struct
- {
- const char *key;
- unicode_char code;
- } codes[] =
+ // for absolute devices, clamp to the bounds absolutely
+ if (!m_wraps)
{
- { "BACKSPACE", 8 },
- { "BS", 8 },
- { "BKSP", 8 },
- { "DEL", UCHAR_MAMEKEY(DEL) },
- { "DELETE", UCHAR_MAMEKEY(DEL) },
- { "END", UCHAR_MAMEKEY(END) },
- { "ENTER", 13 },
- { "ESC", '\033' },
- { "HOME", UCHAR_MAMEKEY(HOME) },
- { "INS", UCHAR_MAMEKEY(INSERT) },
- { "INSERT", UCHAR_MAMEKEY(INSERT) },
- { "PGDN", UCHAR_MAMEKEY(PGDN) },
- { "PGUP", UCHAR_MAMEKEY(PGUP) },
- { "SPACE", 32 },
- { "TAB", 9 },
- { "F1", UCHAR_MAMEKEY(F1) },
- { "F2", UCHAR_MAMEKEY(F2) },
- { "F3", UCHAR_MAMEKEY(F3) },
- { "F4", UCHAR_MAMEKEY(F4) },
- { "F5", UCHAR_MAMEKEY(F5) },
- { "F6", UCHAR_MAMEKEY(F6) },
- { "F7", UCHAR_MAMEKEY(F7) },
- { "F8", UCHAR_MAMEKEY(F8) },
- { "F9", UCHAR_MAMEKEY(F9) },
- { "F10", UCHAR_MAMEKEY(F10) },
- { "F11", UCHAR_MAMEKEY(F11) },
- { "F12", UCHAR_MAMEKEY(F12) },
- { "QUOTE", '\"' }
- };
+ if (value > adjmax)
+ value = adjmax;
+ else if (value < adjmin)
+ value = adjmin;
+ }
- i = 0;
- while(i < text_len)
+ // for relative devices, wrap around when we go past the edge
+ else
{
- ch = text[i];
- increment = 1;
-
- if (ch == '{')
- {
- for (j = 0; j < ARRAY_LENGTH(codes); j++)
- {
- key_len = strlen(codes[j].key);
- if (i + key_len + 2 <= text_len)
- {
- if (!core_strnicmp(codes[j].key, &text[i + 1], key_len) && (text[i + key_len + 1] == '}'))
- {
- ch = codes[j].code;
- increment = key_len + 2;
- }
- }
- }
- }
-
- if (ch)
- inputx_postc_rate(machine, ch, rate);
- i += increment;
+ INT32 range = adjmax - adjmin;
+ // rolls to other end when 1 position past end.
+ value = (value - adjmin) % range;
+ if (value < 0)
+ value += range;
+ value += adjmin;
}
+
+ return value;
}
+//-------------------------------------------------
+// apply_sensitivity - apply a sensitivity
+// adjustment for a current value
+//-------------------------------------------------
-/***************************************************************************
+inline ioport_value analog_field::apply_sensitivity(ioport_value value) const
+{
+ return INT32((INT64(value) * m_sensitivity) / 100.0 + 0.5);
+}
- Alternative calls
-***************************************************************************/
+//-------------------------------------------------
+// apply_inverse_sensitivity - reverse-apply the
+// sensitivity adjustment for a current value
+//-------------------------------------------------
-static void inputx_postc_rate(running_machine &machine, unicode_char ch, attotime rate)
+inline ioport_value analog_field::apply_inverse_sensitivity(ioport_value value) const
{
- inputx_postn_rate(machine, &ch, 1, rate);
+ return INT32((INT64(value) * 100) / m_sensitivity);
}
-void inputx_postc(running_machine &machine, unicode_char ch)
+
+//-------------------------------------------------
+// apply_settings - return the value of an
+// analog input
+//-------------------------------------------------
+
+ioport_value analog_field::apply_settings(ioport_value value) const
{
- inputx_postc_rate(machine, ch, attotime::zero);
+ // apply the min/max and then the sensitivity
+ value = apply_min_max(value);
+ value = apply_sensitivity(value);
+
+ // apply reversal if needed
+ if (m_reverse)
+ value = m_reverse_val - value;
+ else if (m_single_scale)
+ // it's a pedal or the default value is equal to min/max
+ // so we need to adjust the center to the minimum
+ value -= INPUT_ABSOLUTE_MIN;
+
+ // map differently for positive and negative values
+ if (value >= 0)
+ value = apply_scale(value, m_scalepos);
+ else
+ value = apply_scale(value, m_scaleneg);
+ value += m_adjdefvalue;
+
+ return value;
}
-static void inputx_postn_utf8_rate(running_machine &machine, const char *text, size_t text_len, attotime rate)
+
+//-------------------------------------------------
+// frame_update - update the internals of a
+// single analog field periodically
+//-------------------------------------------------
+
+void analog_field::frame_update(running_machine &machine)
{
- size_t len = 0;
- unicode_char buf[256];
- unicode_char c;
- int rc;
+ // clamp the previous value to the min/max range and remember it
+ m_previous = m_accum = apply_min_max(m_accum);
- while(text_len > 0)
+ // get the new raw analog value and its type
+ input_item_class itemclass;
+ INT32 rawvalue = machine.input().seq_axis_value(m_field.seq(SEQ_TYPE_STANDARD), itemclass);
+
+ // if we got an absolute input, it overrides everything else
+ if (itemclass == ITEM_CLASS_ABSOLUTE)
{
- if (len == ARRAY_LENGTH(buf))
+ if (m_previousanalog != rawvalue)
{
- inputx_postn_rate(machine, buf, len, attotime::zero);
- len = 0;
- }
+ // only update if analog value changed
+ m_previousanalog = rawvalue;
+
+ // apply the inverse of the sensitivity to the raw value so that
+ // it will still cover the full min->max range requested after
+ // we apply the sensitivity adjustment
+ if (m_absolute || m_field.analog_reset())
+ {
+ // if port is absolute, then just return the absolute data supplied
+ m_accum = apply_inverse_sensitivity(rawvalue);
+ }
+ else if (m_positionalscale != 0)
+ {
+ // if port is positional, we will take the full analog control and divide it
+ // into positions, that way as the control is moved full scale,
+ // it moves through all the positions
+ rawvalue = apply_scale(rawvalue - INPUT_ABSOLUTE_MIN, m_positionalscale) * INPUT_RELATIVE_PER_PIXEL + m_minimum;
+
+ // clamp the high value so it does not roll over
+ rawvalue = MIN(rawvalue, m_maximum);
+ m_accum = apply_inverse_sensitivity(rawvalue);
+ }
+ else
+ // if port is relative, we use the value to simulate the speed of relative movement
+ // sensitivity adjustment is allowed for this mode
+ m_accum += rawvalue;
- rc = uchar_from_utf8(&c, text, text_len);
- if (rc < 0)
+ m_lastdigital = false;
+ // do not bother with other control types if the analog data is changing
+ return;
+ }
+ else
{
- rc = 1;
- c = INVALID_CHAR;
+ // we still have to update fake relative from joystick control
+ if (!m_absolute && m_positionalscale == 0)
+ m_accum += rawvalue;
}
- text += rc;
- text_len -= rc;
- buf[len++] = c;
}
- inputx_postn_rate(machine, buf, len, rate);
-}
-
-void inputx_post_utf8(running_machine &machine, const char *text)
-{
- inputx_postn_utf8_rate(machine, text, strlen(text), attotime::zero);
-}
-
-void inputx_post_utf8_rate(running_machine &machine, const char *text, attotime rate)
-{
- inputx_postn_utf8_rate(machine, text, strlen(text), rate);
-}
-
-/***************************************************************************
- Other stuff
+ // if we got it from a relative device, use that as the starting delta
+ // also note that the last input was not a digital one
+ INT32 delta = 0;
+ if (itemclass == ITEM_CLASS_RELATIVE && rawvalue != 0)
+ {
+ delta = rawvalue;
+ m_lastdigital = false;
+ }
- This stuff is here more out of convienience than anything else
-***************************************************************************/
+ INT64 keyscale = (m_accum >= 0) ? m_keyscalepos : m_keyscaleneg;
-int input_classify_port(const input_field_config *field)
-{
- int result;
+ // if the decrement code sequence is pressed, add the key delta to
+ // the accumulated delta; also note that the last input was a digital one
+ bool keypressed = false;
+ if (machine.input().seq_pressed(m_field.seq(SEQ_TYPE_DECREMENT)))
+ {
+ keypressed = true;
+ if (m_delta != 0)
+ delta -= apply_scale(m_delta, keyscale);
+ else if (!m_lastdigital)
+ // decrement only once when first pressed
+ delta -= apply_scale(1, keyscale);
+ m_lastdigital = true;
+ }
- switch(field->type)
+ // same for the increment code sequence
+ if (machine.input().seq_pressed(m_field.seq(SEQ_TYPE_INCREMENT)))
{
- case IPT_JOYSTICK_UP:
- case IPT_JOYSTICK_DOWN:
- case IPT_JOYSTICK_LEFT:
- case IPT_JOYSTICK_RIGHT:
- case IPT_JOYSTICKLEFT_UP:
- case IPT_JOYSTICKLEFT_DOWN:
- case IPT_JOYSTICKLEFT_LEFT:
- case IPT_JOYSTICKLEFT_RIGHT:
- case IPT_JOYSTICKRIGHT_UP:
- case IPT_JOYSTICKRIGHT_DOWN:
- case IPT_JOYSTICKRIGHT_LEFT:
- case IPT_JOYSTICKRIGHT_RIGHT:
- case IPT_BUTTON1:
- case IPT_BUTTON2:
- case IPT_BUTTON3:
- case IPT_BUTTON4:
- case IPT_BUTTON5:
- case IPT_BUTTON6:
- case IPT_BUTTON7:
- case IPT_BUTTON8:
- case IPT_BUTTON9:
- case IPT_BUTTON10:
- case IPT_AD_STICK_X:
- case IPT_AD_STICK_Y:
- case IPT_AD_STICK_Z:
- case IPT_TRACKBALL_X:
- case IPT_TRACKBALL_Y:
- case IPT_LIGHTGUN_X:
- case IPT_LIGHTGUN_Y:
- case IPT_MOUSE_X:
- case IPT_MOUSE_Y:
- case IPT_START:
- case IPT_SELECT:
- result = INPUT_CLASS_CONTROLLER;
- break;
+ keypressed = true;
+ if (m_delta)
+ delta += apply_scale(m_delta, keyscale);
+ else if (!m_lastdigital)
+ // increment only once when first pressed
+ delta += apply_scale(1, keyscale);
+ m_lastdigital = true;
+ }
- case IPT_KEYPAD:
- case IPT_KEYBOARD:
- result = INPUT_CLASS_KEYBOARD;
- break;
+ // if resetting is requested, clear the accumulated position to 0 before
+ // applying the deltas so that we only return this frame's delta
+ // note that centering only works for relative controls
+ // no need to check if absolute here because it is checked by the validity tests
+ if (m_field.analog_reset())
+ m_accum = 0;
- case IPT_CONFIG:
- result = INPUT_CLASS_CONFIG;
- break;
+ // apply the delta to the accumulated value
+ m_accum += delta;
- case IPT_DIPSWITCH:
- result = INPUT_CLASS_DIPSWITCH;
- break;
+ // if our last movement was due to a digital input, and if this control
+ // type autocenters, and if neither the increment nor the decrement seq
+ // was pressed, apply autocentering
+ if (m_autocenter)
+ {
+ INT32 center = apply_inverse_sensitivity(m_center);
+ if (m_lastdigital && !keypressed)
+ {
+ // autocenter from positive values
+ if (m_accum >= center)
+ {
+ m_accum -= apply_scale(m_centerdelta, m_keyscalepos);
+ if (m_accum < center)
+ {
+ m_accum = center;
+ m_lastdigital = false;
+ }
+ }
- case 0:
- if (field->name && (field->name != (const char *) -1))
- result = INPUT_CLASS_MISC;
+ // autocenter from negative values
else
- result = INPUT_CLASS_INTERNAL;
- break;
-
- default:
- result = INPUT_CLASS_INTERNAL;
- break;
+ {
+ m_accum += apply_scale(m_centerdelta, m_keyscaleneg);
+ if (m_accum > center)
+ {
+ m_accum = center;
+ m_lastdigital = false;
+ }
+ }
+ }
}
- return result;
+ else if (!keypressed)
+ m_lastdigital = false;
}
+//-------------------------------------------------
+// read - read the current value and insert into
+// the provided ioport_value
+//-------------------------------------------------
-int input_player_number(const input_field_config *port)
+void analog_field::read(ioport_value &result)
{
- return port->player;
-}
+ // do nothing if we're not enabled
+ if (!m_field.enabled())
+ return;
+ // start with the raw value
+ INT32 value = m_accum;
+ // interpolate if appropriate and if time has passed since the last update
+ if (m_interpolate)
+ value = manager().frame_interpolate(m_previous, m_accum);
-/*-------------------------------------------------
- input_has_input_class - checks to see if a
- particular input class is present
--------------------------------------------------*/
+ // apply standard analog settings
+ value = apply_settings(value);
-int input_has_input_class(running_machine &machine, int inputclass)
-{
- const input_port_config *port;
- const input_field_config *field;
+ // remap the value if needed
+ if (m_field.remap_table() != NULL)
+ value = m_field.remap_table()[value];
- for (port = machine.ioport().first_port(); port != NULL; port = port->next())
- {
- for (field = port->first_field(); field != NULL; field = field->next())
- {
- if (input_classify_port(field) == inputclass)
- return TRUE;
- }
- }
- return FALSE;
-}
+ // invert bits if needed
+ if (m_field.analog_invert())
+ value = ~value;
+ // insert into the port
+ result = (result & ~m_field.mask()) | ((value << m_shift) & m_field.mask());
+}
-/*-------------------------------------------------
- input_count_players - counts the number of
- active players
--------------------------------------------------*/
+//-------------------------------------------------
+// crosshair_read - read a value for crosshairs,
+// scaled between 0 and 1
+//-------------------------------------------------
-int input_count_players(running_machine &machine)
+float analog_field::crosshair_read()
{
- const input_port_config *port;
- const input_field_config *field;
- int joystick_count;
-
- joystick_count = 0;
- for (port = machine.ioport().first_port(); port != NULL; port = port->next())
- {
- for (field = port->first_field(); field != NULL; field = field->next())
- {
- if (input_classify_port(field) == INPUT_CLASS_CONTROLLER)
- {
- if (joystick_count <= field->player + 1)
- joystick_count = field->player + 1;
- }
- }
- }
- return joystick_count;
+ INT32 rawvalue = apply_settings(m_accum) & (m_field.mask() >> m_shift);
+ return float(rawvalue - m_adjmin) / float(m_adjmax - m_adjmin);
}
/***************************************************************************
- DEBUGGER SUPPORT
+ TOKENIZATION HELPERS
***************************************************************************/
-/*-------------------------------------------------
- execute_input - debugger command to enter
- natural keyboard input
--------------------------------------------------*/
+//-------------------------------------------------
+// token_to_input_type - convert a string token
+// to an input field type and player
+//-------------------------------------------------
-static void execute_input(running_machine &machine, int ref, int params, const char *param[])
+ioport_type ioport_manager::token_to_input_type(const char *string, int &player) const
{
- inputx_postn_coded_rate(machine, param[0], strlen(param[0]), attotime::zero);
-}
-
-
-
-/*-------------------------------------------------
- execute_dumpkbd - debugger command to natural
- keyboard codes
--------------------------------------------------*/
+ // check for our failsafe case first
+ int ipnum;
+ if (sscanf(string, "TYPE_OTHER(%d,%d)", &ipnum, &player) == 2)
+ return ioport_type(ipnum);
-static void execute_dumpkbd(running_machine &machine, int ref, int params, const char *param[])
-{
- inputx_code *codes = machine.ioport().codes;
- const char *filename;
- FILE *file = NULL;
- const inputx_code *code;
- char buffer[512];
- size_t pos;
- int i, j;
- size_t left_column_width = 24;
-
- /* was there a file specified? */
- filename = (params > 0) ? param[0] : NULL;
- if (filename != NULL)
- {
- /* if so, open it */
- file = fopen(filename, "w");
- if (file == NULL)
+ // find the token in the list
+ for (input_type_entry *entry = m_typelist.first(); entry != NULL; entry = entry->next())
+ if (entry->token() != NULL && !strcmp(entry->token(), string))
{
- debug_console_printf(machine, "Cannot open \"%s\"\n", filename);
- return;
+ player = entry->player();
+ return entry->type();
}
- }
-
- if ((codes != NULL) && (codes[0].ch != 0))
- {
- /* loop through all codes */
- for (i = 0; codes[i].ch; i++)
- {
- code = &codes[i];
- pos = 0;
- /* describe the character code */
- pos += snprintf(&buffer[pos], ARRAY_LENGTH(buffer) - pos, "%08X (%s) ",
- code->ch,
- code_point_string(machine, code->ch));
-
- /* pad with spaces */
- while(pos < left_column_width)
- buffer[pos++] = ' ';
- buffer[pos] = '\0';
+ // if we fail, return IPT_UNKNOWN
+ player = 0;
+ return IPT_UNKNOWN;
+}
- /* identify the keys used */
- for (j = 0; j < ARRAY_LENGTH(code->field) && (code->field[j] != NULL); j++)
- {
- pos += snprintf(&buffer[pos], ARRAY_LENGTH(buffer) - pos, "%s'%s'",
- (j > 0) ? ", " : "",
- code->field[j]->name);
- }
- /* and output it as appropriate */
- if (file != NULL)
- fprintf(file, "%s\n", buffer);
- else
- debug_console_printf(machine, "%s\n", buffer);
- }
- }
- else
- {
- debug_console_printf(machine, "No natural keyboard support\n");
- }
+//-------------------------------------------------
+// input_type_to_token - convert an input field
+// type and player to a string token
+//-------------------------------------------------
- /* cleanup */
- if (file != NULL)
- fclose(file);
+const char *ioport_manager::input_type_to_token(astring &string, ioport_type type, int player)
+{
+ // look up the port and return the token
+ input_type_entry *entry = m_type_to_entry[type][player];
+ if (entry != NULL)
+ return string.cpy(entry->token());
+ // if that fails, carry on
+ return string.format("TYPE_OTHER(%d,%d)", type, player);
}
+//-------------------------------------------------
+// token_to_seq_type - convert a string to
+// a sequence type
+//-------------------------------------------------
-input_port_config *ioconfig_alloc_port(ioport_list &portlist, device_t &device, const char *tag)
+input_seq_type ioport_manager::token_to_seq_type(const char *string)
{
- astring fulltag;
- device.subtag(fulltag, tag);
- return &portlist.append(fulltag, *global_alloc(input_port_config(device, fulltag)));
+ // look up the string in the table of possible sequence types and return the index
+ for (int seqindex = 0; seqindex < ARRAY_LENGTH(seqtypestrings); seqindex++)
+ if (!mame_stricmp(string, seqtypestrings[seqindex]))
+ return input_seq_type(seqindex);
+ return SEQ_TYPE_INVALID;
}
-input_port_config *ioconfig_modify_port(ioport_list &portlist, device_t &device, const char *tag)
-{
- astring fulltag;
- device.subtag(fulltag, tag);
- input_port_config *port = portlist.find(fulltag.cstr());
- if (port == NULL)
- throw emu_fatalerror("Requested to modify nonexistent port '%s'", fulltag.cstr());
- port->bump_modcount();
- return port;
-}
-input_field_config *ioconfig_alloc_field(input_port_config &port, int type, input_port_value defval, input_port_value mask, const char *name)
-{
- if (&port == NULL)
- throw emu_fatalerror("INPUT_TOKEN_FIELD encountered with no active port (mask=%X defval=%X)\n", mask, defval); \
- if (type != IPT_UNKNOWN && type != IPT_UNUSED)
- port.active |= mask;
- if (type == IPT_DIPSWITCH || type == IPT_CONFIG)
- defval = port_default_value(port.tag(), mask, defval, port.owner());
- return &port.fieldlist().append(*global_alloc(input_field_config(port, type, defval, mask, input_port_string_from_token(name))));
-}
-input_field_config *ioconfig_alloc_onoff(input_port_config &port, const char *name, input_port_value defval, input_port_value mask, const char *diplocation, astring &errorbuf)
-{
- input_field_config *curfield = ioconfig_alloc_field(port, IPT_DIPSWITCH, defval, mask, name);
- if (name == DEF_STR(Service_Mode))
- {
- curfield->flags |= FIELD_FLAG_TOGGLE;
- curfield->seq[SEQ_TYPE_STANDARD].set(KEYCODE_F2);
- }
- if (diplocation != NULL)
- diplocation_list_alloc(*curfield, diplocation, errorbuf);
- ioconfig_alloc_setting(*curfield, defval & mask, DEF_STR(Off));
- ioconfig_alloc_setting(*curfield, ~defval & mask, DEF_STR(On));
- return curfield;
-}
+//-------------------------------------------------
+// validate_natural_keyboard_statics -
+// validates natural keyboard static data
+//-------------------------------------------------
-input_setting_config *ioconfig_alloc_setting(input_field_config &field, input_port_value value, const char *name)
+/*
+int validate_natural_keyboard_statics(void)
{
- return &field.settinglist().append(*global_alloc(input_setting_config(field, value, input_port_string_from_token(name))));
-}
+ int i;
+ int error = FALSE;
+ unicode_char last_char = 0;
+ const char_info *ci;
-void ioconfig_field_add_char(input_field_config &field, unicode_char ch, astring &errorbuf)
-{
- for (int index = 0; index < ARRAY_LENGTH(field.chars); index++)
- if (field.chars[index] == 0)
+ // check to make sure that charinfo is in order
+ for (i = 0; i < ARRAY_LENGTH(charinfo); i++)
+ {
+ if (last_char >= charinfo[i].ch)
{
- field.chars[index] = ch;
- break;
+ mame_printf_error("inputx: charinfo is out of order; 0x%08x should be higher than 0x%08x\n", charinfo[i].ch, last_char);
+ error = TRUE;
}
-}
+ last_char = charinfo[i].ch;
+ }
-void ioconfig_add_code(input_field_config &field, int which, input_code code)
-{
- field.seq[which] |= code;
+ // check to make sure that I can look up everything on alternate_charmap
+ for (i = 0; i < ARRAY_LENGTH(charinfo); i++)
+ {
+ ci = char_info::find(charinfo[i].ch);
+ if (ci != &charinfo[i])
+ {
+ mame_printf_error("ioport: expected char_info::find(0x%08x) to work properly\n", charinfo[i].ch);
+ error = TRUE;
+ }
+ }
+ return error;
}
+*/
-
-input_type_entry::input_type_entry(UINT32 _type, ioport_group _group, int _player, const char *_token, const char *_name, input_seq standard)
- : type(_type),
- group(_group),
- player(_player),
- token(_token),
- name(_name),
- m_next(NULL)
-{
- defseq[SEQ_TYPE_STANDARD] = seq[SEQ_TYPE_STANDARD] = standard;
-}
-
-input_type_entry::input_type_entry(UINT32 _type, ioport_group _group, int _player, const char *_token, const char *_name, input_seq standard, input_seq decrement, input_seq increment)
- : type(_type),
- group(_group),
- player(_player),
- token(_token),
- name(_name),
- m_next(NULL)
-{
- defseq[SEQ_TYPE_STANDARD] = seq[SEQ_TYPE_STANDARD] = standard;
- defseq[SEQ_TYPE_INCREMENT] = seq[SEQ_TYPE_INCREMENT] = increment;
- defseq[SEQ_TYPE_DECREMENT] = seq[SEQ_TYPE_DECREMENT] = decrement;
-}
diff --git a/src/emu/ioport.h b/src/emu/ioport.h
index 8856e15ae4a..21050a6fb57 100644
--- a/src/emu/ioport.h
+++ b/src/emu/ioport.h
@@ -4,8 +4,36 @@
Input/output port handling.
- Copyright Nicola Salmoria and the MAME Team.
- Visit http://mamedev.org for licensing and usage restrictions.
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/
@@ -21,61 +49,48 @@
#include <time.h>
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
-/***************************************************************************
- CONSTANTS
-***************************************************************************/
-
-#define MAX_PLAYERS 8
-
-#define IP_ACTIVE_HIGH 0x00000000
-#define IP_ACTIVE_LOW 0xffffffff
+// input ports support up to 32 bits each
+typedef UINT32 ioport_value;
+// active high/low values for input ports
+const ioport_value IP_ACTIVE_HIGH = 0x00000000;
+const ioport_value IP_ACTIVE_LOW = 0xffffffff;
-/* flags for input_field_configs */
-#define FIELD_FLAG_UNUSED 0x01 /* set if this field is unused but relevant to other games on the same hw */
-#define FIELD_FLAG_COCKTAIL 0x02 /* set if this field is relevant only for cocktail cabinets */
-#define FIELD_FLAG_TOGGLE 0x04 /* set if this field should behave as a toggle */
-#define FIELD_FLAG_ROTATED 0x08 /* set if this field represents a rotated control */
-#define ANALOG_FLAG_REVERSE 0x10 /* analog only: reverse the sense of the axis */
-#define ANALOG_FLAG_RESET 0x20 /* analog only: always preload in->default for relative axes, returning only deltas */
-#define ANALOG_FLAG_WRAPS 0x40 /* analog only: positional count wraps around */
-#define ANALOG_FLAG_INVERT 0x80 /* analog only: bitwise invert bits */
+// maximum number of players supported
+const int MAX_PLAYERS = 8;
+// INP file parameters
+const UINT32 INP_HEADER_SIZE = 64;
+const UINT32 INP_HEADER_MAJVERSION = 3;
+const UINT32 INP_HEADER_MINVERSION = 0;
-/* INP file information */
-#define INP_HEADER_SIZE 64
-#define INP_HEADER_MAJVERSION 3
-#define INP_HEADER_MINVERSION 0
+// unicode constants
+const unicode_char UCHAR_PRIVATE = 0x100000;
+const unicode_char UCHAR_SHIFT_1 = UCHAR_PRIVATE + 0;
+const unicode_char UCHAR_SHIFT_2 = UCHAR_PRIVATE + 1;
+const unicode_char UCHAR_SHIFT_BEGIN = UCHAR_SHIFT_1;
+const unicode_char UCHAR_SHIFT_END = UCHAR_SHIFT_2;
+const unicode_char UCHAR_MAMEKEY_BEGIN = UCHAR_PRIVATE + 2;
-/* sequence types for input_port_seq() call */
-enum _input_seq_type
+// sequence types for input_port_seq() call
+enum input_seq_type
{
+ SEQ_TYPE_INVALID = -1,
SEQ_TYPE_STANDARD = 0,
SEQ_TYPE_INCREMENT,
SEQ_TYPE_DECREMENT,
SEQ_TYPE_TOTAL
};
-typedef enum _input_seq_type input_seq_type;
DECLARE_ENUM_OPERATORS(input_seq_type)
-/* conditions for DIP switches */
-enum
-{
- PORTCOND_ALWAYS = 0,
- PORTCOND_EQUALS,
- PORTCOND_NOTEQUALS,
- PORTCOND_GREATERTHAN,
- PORTCOND_NOTGREATERTHAN,
- PORTCOND_LESSTHAN,
- PORTCOND_NOTLESSTHAN
-};
-
-
-/* crosshair types */
-enum
+// crosshair types
+enum crosshair_axis_t
{
CROSSHAIR_AXIS_NONE = 0,
CROSSHAIR_AXIS_X,
@@ -83,7 +98,7 @@ enum
};
-/* groups for input ports */
+// groups for input ports
enum ioport_group
{
IPG_UI = 0,
@@ -101,20 +116,19 @@ enum ioport_group
};
-/* various input port types */
-enum
+// various input port types
+enum ioport_type
{
- /* pseudo-port types */
+ // pseudo-port types
IPT_INVALID = 0,
IPT_UNUSED,
IPT_END,
IPT_UNKNOWN,
IPT_PORT,
IPT_DIPSWITCH,
- IPT_VBLANK,
IPT_CONFIG,
- /* start buttons */
+ // start buttons
IPT_START1,
IPT_START2,
IPT_START3,
@@ -124,7 +138,7 @@ enum
IPT_START7,
IPT_START8,
- /* coin slots */
+ // coin slots
IPT_COIN1,
IPT_COIN2,
IPT_COIN3,
@@ -139,48 +153,51 @@ enum
IPT_COIN12,
IPT_BILL1,
- /* service coin */
+ // service coin
IPT_SERVICE1,
IPT_SERVICE2,
IPT_SERVICE3,
IPT_SERVICE4,
- /* tilt inputs */
+ // tilt inputs
IPT_TILT1,
IPT_TILT2,
IPT_TILT3,
IPT_TILT4,
- /* misc other digital inputs */
+ // misc other digital inputs
IPT_SERVICE,
IPT_TILT,
IPT_INTERLOCK,
IPT_VOLUME_UP,
IPT_VOLUME_DOWN,
- IPT_START, /* MESS only */
- IPT_SELECT, /* MESS only */
- IPT_KEYPAD, /* MESS only */
- IPT_KEYBOARD, /* MESS only */
-
-#define __ipt_digital_joystick_start IPT_JOYSTICK_UP
- /* use IPT_JOYSTICK for panels where the player has one single joystick */
- IPT_JOYSTICK_UP,
- IPT_JOYSTICK_DOWN,
- IPT_JOYSTICK_LEFT,
- IPT_JOYSTICK_RIGHT,
-
- /* use IPT_JOYSTICKLEFT and IPT_JOYSTICKRIGHT for dual joystick panels */
- IPT_JOYSTICKRIGHT_UP,
- IPT_JOYSTICKRIGHT_DOWN,
- IPT_JOYSTICKRIGHT_LEFT,
- IPT_JOYSTICKRIGHT_RIGHT,
- IPT_JOYSTICKLEFT_UP,
- IPT_JOYSTICKLEFT_DOWN,
- IPT_JOYSTICKLEFT_LEFT,
- IPT_JOYSTICKLEFT_RIGHT,
-#define __ipt_digital_joystick_end IPT_JOYSTICKLEFT_RIGHT
-
- /* action buttons */
+ IPT_START, // MESS only
+ IPT_SELECT, // MESS only
+ IPT_KEYPAD, // MESS only
+ IPT_KEYBOARD, // MESS only
+
+ // digital joystick inputs
+ IPT_DIGITAL_JOYSTICK_FIRST,
+
+ // use IPT_JOYSTICK for panels where the player has one single joystick
+ IPT_JOYSTICK_UP = IPT_DIGITAL_JOYSTICK_FIRST,
+ IPT_JOYSTICK_DOWN,
+ IPT_JOYSTICK_LEFT,
+ IPT_JOYSTICK_RIGHT,
+
+ // use IPT_JOYSTICKLEFT and IPT_JOYSTICKRIGHT for dual joystick panels
+ IPT_JOYSTICKRIGHT_UP,
+ IPT_JOYSTICKRIGHT_DOWN,
+ IPT_JOYSTICKRIGHT_LEFT,
+ IPT_JOYSTICKRIGHT_RIGHT,
+ IPT_JOYSTICKLEFT_UP,
+ IPT_JOYSTICKLEFT_DOWN,
+ IPT_JOYSTICKLEFT_LEFT,
+ IPT_JOYSTICKLEFT_RIGHT,
+
+ IPT_DIGITAL_JOYSTICK_LAST,
+
+ // action buttons
IPT_BUTTON1,
IPT_BUTTON2,
IPT_BUTTON3,
@@ -198,210 +215,234 @@ enum
IPT_BUTTON15,
IPT_BUTTON16,
- /* mahjong inputs */
-#define __ipt_mahjong_start IPT_MAHJONG_A
- IPT_MAHJONG_A,
- IPT_MAHJONG_B,
- IPT_MAHJONG_C,
- IPT_MAHJONG_D,
- IPT_MAHJONG_E,
- IPT_MAHJONG_F,
- IPT_MAHJONG_G,
- IPT_MAHJONG_H,
- IPT_MAHJONG_I,
- IPT_MAHJONG_J,
- IPT_MAHJONG_K,
- IPT_MAHJONG_L,
- IPT_MAHJONG_M,
- IPT_MAHJONG_N,
- IPT_MAHJONG_O,
- IPT_MAHJONG_P,
- IPT_MAHJONG_Q,
- IPT_MAHJONG_KAN,
- IPT_MAHJONG_PON,
- IPT_MAHJONG_CHI,
- IPT_MAHJONG_REACH, //IPT_MAHJONG_RIICHI, // REACH is Japanglish
- IPT_MAHJONG_RON,
- IPT_MAHJONG_BET,
- IPT_MAHJONG_LAST_CHANCE,
- IPT_MAHJONG_SCORE,
- IPT_MAHJONG_DOUBLE_UP,
- IPT_MAHJONG_FLIP_FLOP,
- IPT_MAHJONG_BIG,
- IPT_MAHJONG_SMALL,
-#define __ipt_mahjong_end IPT_MAHJONG_SMALL
-
- /* hanafuda inputs */
-#define __ipt_hanafuda_start IPT_HANAFUDA_A
- IPT_HANAFUDA_A,
- IPT_HANAFUDA_B,
- IPT_HANAFUDA_C,
- IPT_HANAFUDA_D,
- IPT_HANAFUDA_E,
- IPT_HANAFUDA_F,
- IPT_HANAFUDA_G,
- IPT_HANAFUDA_H,
- IPT_HANAFUDA_YES,
- IPT_HANAFUDA_NO,
-#define __ipt_hanafuda_end IPT_HANAFUDA_NO
-
-#define __ipt_gambling_start IPT_GAMBLE_KEYIN
-
- /* gambling inputs */
- IPT_GAMBLE_KEYIN, // attendant
- IPT_GAMBLE_KEYOUT, // attendant
- IPT_GAMBLE_SERVICE, // attendant
- IPT_GAMBLE_BOOK, // attendant
- IPT_GAMBLE_DOOR, // attendant
-// IPT_GAMBLE_DOOR2, // many gambling games have several doors.
-// IPT_GAMBLE_DOOR3,
-// IPT_GAMBLE_DOOR4,
-// IPT_GAMBLE_DOOR5,
-
- IPT_GAMBLE_HIGH, // player
- IPT_GAMBLE_LOW, // player
- IPT_GAMBLE_HALF, // player
- IPT_GAMBLE_DEAL, // player
- IPT_GAMBLE_D_UP, // player
- IPT_GAMBLE_TAKE, // player
- IPT_GAMBLE_STAND, // player
- IPT_GAMBLE_BET, // player
- IPT_GAMBLE_PAYOUT, // player
-// IPT_GAMBLE_BUTTON1, // player
-// IPT_GAMBLE_BUTTON2, // many many gambling games have multi-games and/or multi-function-buttons
-// IPT_GAMBLE_BUTTON3, // I suggest to eliminate specific names
-// IPT_GAMBLE_BUTTON4,
-// IPT_GAMBLE_BUTTON5,
-// IPT_GAMBLE_BUTTON6,
-// IPT_GAMBLE_BUTTON7,
-// IPT_GAMBLE_BUTTON8,
-// IPT_GAMBLE_BUTTON9,
-// IPT_GAMBLE_BUTTON10,
-// IPT_GAMBLE_BUTTON11,
-// IPT_GAMBLE_BUTTON12,
-// IPT_GAMBLE_BUTTON13,
-// IPT_GAMBLE_BUTTON14,
-// IPT_GAMBLE_BUTTON15,
-// IPT_GAMBLE_BUTTON16,
-
- /* poker-specific inputs */
- IPT_POKER_HOLD1,
- IPT_POKER_HOLD2,
- IPT_POKER_HOLD3,
- IPT_POKER_HOLD4,
- IPT_POKER_HOLD5,
- IPT_POKER_CANCEL,
- IPT_POKER_BET,
-
- /* slot-specific inputs */
- IPT_SLOT_STOP1,
- IPT_SLOT_STOP2,
- IPT_SLOT_STOP3,
- IPT_SLOT_STOP4,
- IPT_SLOT_STOP_ALL,
-
-#define __ipt_gambling_end IPT_SLOT_STOP_ALL
-
- /* analog inputs */
-#define __ipt_analog_start IPT_AD_STICK_X
-#define __ipt_analog_absolute_start IPT_AD_STICK_X
- IPT_AD_STICK_X, // absolute // autocenter
- IPT_AD_STICK_Y, // absolute // autocenter
- IPT_AD_STICK_Z, // absolute // autocenter
- IPT_PADDLE, // absolute // autocenter
- IPT_PADDLE_V, // absolute // autocenter
- IPT_PEDAL, // absolute // autocenter
- IPT_PEDAL2, // absolute // autocenter
- IPT_PEDAL3, // absolute // autocenter
- IPT_LIGHTGUN_X, // absolute
- IPT_LIGHTGUN_Y, // absolute
- IPT_POSITIONAL, // absolute // autocenter if not wraps
- IPT_POSITIONAL_V, // absolute // autocenter if not wraps
-#define __ipt_analog_absolute_end IPT_POSITIONAL_V
-
- IPT_DIAL, // relative
- IPT_DIAL_V, // relative
- IPT_TRACKBALL_X, // relative
- IPT_TRACKBALL_Y, // relative
- IPT_MOUSE_X, // relative
- IPT_MOUSE_Y, // relative
-#define __ipt_analog_end IPT_MOUSE_Y
-
- /* analog adjuster support */
+ // mahjong inputs
+ IPT_MAHJONG_FIRST,
+
+ IPT_MAHJONG_A,
+ IPT_MAHJONG_B,
+ IPT_MAHJONG_C,
+ IPT_MAHJONG_D,
+ IPT_MAHJONG_E,
+ IPT_MAHJONG_F,
+ IPT_MAHJONG_G,
+ IPT_MAHJONG_H,
+ IPT_MAHJONG_I,
+ IPT_MAHJONG_J,
+ IPT_MAHJONG_K,
+ IPT_MAHJONG_L,
+ IPT_MAHJONG_M,
+ IPT_MAHJONG_N,
+ IPT_MAHJONG_O,
+ IPT_MAHJONG_P,
+ IPT_MAHJONG_Q,
+ IPT_MAHJONG_KAN,
+ IPT_MAHJONG_PON,
+ IPT_MAHJONG_CHI,
+ IPT_MAHJONG_REACH, //IPT_MAHJONG_RIICHI, // REACH is Japanglish
+ IPT_MAHJONG_RON,
+ IPT_MAHJONG_BET,
+ IPT_MAHJONG_LAST_CHANCE,
+ IPT_MAHJONG_SCORE,
+ IPT_MAHJONG_DOUBLE_UP,
+ IPT_MAHJONG_FLIP_FLOP,
+ IPT_MAHJONG_BIG,
+ IPT_MAHJONG_SMALL,
+
+ IPT_MAHJONG_LAST,
+
+ // hanafuda inputs
+ IPT_HANAFUDA_FIRST,
+
+ IPT_HANAFUDA_A,
+ IPT_HANAFUDA_B,
+ IPT_HANAFUDA_C,
+ IPT_HANAFUDA_D,
+ IPT_HANAFUDA_E,
+ IPT_HANAFUDA_F,
+ IPT_HANAFUDA_G,
+ IPT_HANAFUDA_H,
+ IPT_HANAFUDA_YES,
+ IPT_HANAFUDA_NO,
+
+ IPT_HANAFUDA_LAST,
+
+ // gambling inputs
+ IPT_GAMBLING_FIRST,
+
+ IPT_GAMBLE_KEYIN, // attendant
+ IPT_GAMBLE_KEYOUT, // attendant
+ IPT_GAMBLE_SERVICE, // attendant
+ IPT_GAMBLE_BOOK, // attendant
+ IPT_GAMBLE_DOOR, // attendant
+ // IPT_GAMBLE_DOOR2, // many gambling games have several doors.
+ // IPT_GAMBLE_DOOR3,
+ // IPT_GAMBLE_DOOR4,
+ // IPT_GAMBLE_DOOR5,
+
+ IPT_GAMBLE_HIGH, // player
+ IPT_GAMBLE_LOW, // player
+ IPT_GAMBLE_HALF, // player
+ IPT_GAMBLE_DEAL, // player
+ IPT_GAMBLE_D_UP, // player
+ IPT_GAMBLE_TAKE, // player
+ IPT_GAMBLE_STAND, // player
+ IPT_GAMBLE_BET, // player
+ IPT_GAMBLE_PAYOUT, // player
+ // IPT_GAMBLE_BUTTON1, // player
+ // IPT_GAMBLE_BUTTON2, // many many gambling games have multi-games and/or multi-function-buttons
+ // IPT_GAMBLE_BUTTON3, // I suggest to eliminate specific names
+ // IPT_GAMBLE_BUTTON4,
+ // IPT_GAMBLE_BUTTON5,
+ // IPT_GAMBLE_BUTTON6,
+ // IPT_GAMBLE_BUTTON7,
+ // IPT_GAMBLE_BUTTON8,
+ // IPT_GAMBLE_BUTTON9,
+ // IPT_GAMBLE_BUTTON10,
+ // IPT_GAMBLE_BUTTON11,
+ // IPT_GAMBLE_BUTTON12,
+ // IPT_GAMBLE_BUTTON13,
+ // IPT_GAMBLE_BUTTON14,
+ // IPT_GAMBLE_BUTTON15,
+ // IPT_GAMBLE_BUTTON16,
+
+ // poker-specific inputs
+ IPT_POKER_HOLD1,
+ IPT_POKER_HOLD2,
+ IPT_POKER_HOLD3,
+ IPT_POKER_HOLD4,
+ IPT_POKER_HOLD5,
+ IPT_POKER_CANCEL,
+ IPT_POKER_BET,
+
+ // slot-specific inputs
+ IPT_SLOT_STOP1,
+ IPT_SLOT_STOP2,
+ IPT_SLOT_STOP3,
+ IPT_SLOT_STOP4,
+ IPT_SLOT_STOP_ALL,
+
+ IPT_GAMBLING_LAST,
+
+ // analog inputs
+ IPT_ANALOG_FIRST,
+
+ IPT_ANALOG_ABSOLUTE_FIRST,
+
+ IPT_AD_STICK_X, // absolute // autocenter
+ IPT_AD_STICK_Y, // absolute // autocenter
+ IPT_AD_STICK_Z, // absolute // autocenter
+ IPT_PADDLE, // absolute // autocenter
+ IPT_PADDLE_V, // absolute // autocenter
+ IPT_PEDAL, // absolute // autocenter
+ IPT_PEDAL2, // absolute // autocenter
+ IPT_PEDAL3, // absolute // autocenter
+ IPT_LIGHTGUN_X, // absolute
+ IPT_LIGHTGUN_Y, // absolute
+ IPT_POSITIONAL, // absolute // autocenter if not wraps
+ IPT_POSITIONAL_V, // absolute // autocenter if not wraps
+
+ IPT_ANALOG_ABSOLUTE_LAST,
+
+ IPT_DIAL, // relative
+ IPT_DIAL_V, // relative
+ IPT_TRACKBALL_X, // relative
+ IPT_TRACKBALL_Y, // relative
+ IPT_MOUSE_X, // relative
+ IPT_MOUSE_Y, // relative
+
+ IPT_ANALOG_LAST,
+
+ // analog adjuster support
IPT_ADJUSTER,
- /* the following are special codes for user interface handling - not to be used by drivers! */
-#define __ipt_ui_start IPT_UI_CONFIGURE
- IPT_UI_CONFIGURE,
- IPT_UI_ON_SCREEN_DISPLAY,
- IPT_UI_DEBUG_BREAK,
- IPT_UI_PAUSE,
- IPT_UI_RESET_MACHINE,
- IPT_UI_SOFT_RESET,
- IPT_UI_SHOW_GFX,
- IPT_UI_FRAMESKIP_DEC,
- IPT_UI_FRAMESKIP_INC,
- IPT_UI_THROTTLE,
- IPT_UI_FAST_FORWARD,
- IPT_UI_SHOW_FPS,
- IPT_UI_SNAPSHOT,
- IPT_UI_RECORD_MOVIE,
- IPT_UI_TOGGLE_CHEAT,
- IPT_UI_UP,
- IPT_UI_DOWN,
- IPT_UI_LEFT,
- IPT_UI_RIGHT,
- IPT_UI_HOME,
- IPT_UI_END,
- IPT_UI_PAGE_UP,
- IPT_UI_PAGE_DOWN,
- IPT_UI_SELECT,
- IPT_UI_CANCEL,
- IPT_UI_DISPLAY_COMMENT,
- IPT_UI_CLEAR,
- IPT_UI_ZOOM_IN,
- IPT_UI_ZOOM_OUT,
- IPT_UI_PREV_GROUP,
- IPT_UI_NEXT_GROUP,
- IPT_UI_ROTATE,
- IPT_UI_SHOW_PROFILER,
- IPT_UI_TOGGLE_UI,
- IPT_UI_TOGGLE_DEBUG,
- IPT_UI_PASTE,
- IPT_UI_SAVE_STATE,
- IPT_UI_LOAD_STATE,
-
- /* additional OSD-specified UI port types (up to 16) */
- IPT_OSD_1,
- IPT_OSD_2,
- IPT_OSD_3,
- IPT_OSD_4,
- IPT_OSD_5,
- IPT_OSD_6,
- IPT_OSD_7,
- IPT_OSD_8,
- IPT_OSD_9,
- IPT_OSD_10,
- IPT_OSD_11,
- IPT_OSD_12,
- IPT_OSD_13,
- IPT_OSD_14,
- IPT_OSD_15,
- IPT_OSD_16,
-#define __ipt_ui_end IPT_OSD_16
-
- /* other meaning not mapped to standard defaults */
+ // the following are special codes for user interface handling - not to be used by drivers!
+ IPT_UI_FIRST,
+
+ IPT_UI_CONFIGURE,
+ IPT_UI_ON_SCREEN_DISPLAY,
+ IPT_UI_DEBUG_BREAK,
+ IPT_UI_PAUSE,
+ IPT_UI_RESET_MACHINE,
+ IPT_UI_SOFT_RESET,
+ IPT_UI_SHOW_GFX,
+ IPT_UI_FRAMESKIP_DEC,
+ IPT_UI_FRAMESKIP_INC,
+ IPT_UI_THROTTLE,
+ IPT_UI_FAST_FORWARD,
+ IPT_UI_SHOW_FPS,
+ IPT_UI_SNAPSHOT,
+ IPT_UI_RECORD_MOVIE,
+ IPT_UI_TOGGLE_CHEAT,
+ IPT_UI_UP,
+ IPT_UI_DOWN,
+ IPT_UI_LEFT,
+ IPT_UI_RIGHT,
+ IPT_UI_HOME,
+ IPT_UI_END,
+ IPT_UI_PAGE_UP,
+ IPT_UI_PAGE_DOWN,
+ IPT_UI_SELECT,
+ IPT_UI_CANCEL,
+ IPT_UI_DISPLAY_COMMENT,
+ IPT_UI_CLEAR,
+ IPT_UI_ZOOM_IN,
+ IPT_UI_ZOOM_OUT,
+ IPT_UI_PREV_GROUP,
+ IPT_UI_NEXT_GROUP,
+ IPT_UI_ROTATE,
+ IPT_UI_SHOW_PROFILER,
+ IPT_UI_TOGGLE_UI,
+ IPT_UI_TOGGLE_DEBUG,
+ IPT_UI_PASTE,
+ IPT_UI_SAVE_STATE,
+ IPT_UI_LOAD_STATE,
+
+ // additional OSD-specified UI port types (up to 16)
+ IPT_OSD_1,
+ IPT_OSD_2,
+ IPT_OSD_3,
+ IPT_OSD_4,
+ IPT_OSD_5,
+ IPT_OSD_6,
+ IPT_OSD_7,
+ IPT_OSD_8,
+ IPT_OSD_9,
+ IPT_OSD_10,
+ IPT_OSD_11,
+ IPT_OSD_12,
+ IPT_OSD_13,
+ IPT_OSD_14,
+ IPT_OSD_15,
+ IPT_OSD_16,
+
+ IPT_UI_LAST,
+
+ // other meaning not mapped to standard defaults
IPT_OTHER,
- /* special meaning handled by custom code */
+ // special meaning handled by custom code
IPT_SPECIAL,
+ IPT_CUSTOM,
IPT_OUTPUT,
- __ipt_max
+ IPT_COUNT
+};
+DECLARE_ENUM_OPERATORS(ioport_type)
+
+
+// input type classes
+enum ioport_type_class
+{
+ INPUT_CLASS_INTERNAL,
+ INPUT_CLASS_KEYBOARD,
+ INPUT_CLASS_CONTROLLER,
+ INPUT_CLASS_CONFIG,
+ INPUT_CLASS_DIPSWITCH,
+ INPUT_CLASS_MISC
};
-/* default strings used in port definitions */
+// default strings used in port definitions
enum
{
INPUT_STRING_Off = 1,
@@ -627,300 +668,565 @@ enum
};
-/* input classes */
-enum
-{
- INPUT_CLASS_INTERNAL,
- INPUT_CLASS_KEYBOARD,
- INPUT_CLASS_CONTROLLER,
- INPUT_CLASS_CONFIG,
- INPUT_CLASS_DIPSWITCH,
- INPUT_CLASS_MISC
-};
-
-#define UCHAR_PRIVATE (0x100000)
-#define UCHAR_SHIFT_1 (UCHAR_PRIVATE + 0)
-#define UCHAR_SHIFT_2 (UCHAR_PRIVATE + 1)
-#define UCHAR_MAMEKEY_BEGIN (UCHAR_PRIVATE + 2)
-#define UCHAR_MAMEKEY(code) (UCHAR_MAMEKEY_BEGIN + ITEM_ID_##code)
-
-#define UCHAR_SHIFT_BEGIN (UCHAR_SHIFT_1)
-#define UCHAR_SHIFT_END (UCHAR_SHIFT_2)
-
-/***************************************************************************
- TYPE DEFINITIONS
-***************************************************************************/
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
-/* input ports support up to 32 bits each */
-typedef UINT32 input_port_value;
+// opaque types pointing to live state
+struct input_port_state;
+struct input_field_state;
+// forward declarations
+class ioport_list;
+class ioport_port;
+struct ioport_port_live;
+class ioport_field;
+struct ioport_field_live;
+class ioport_manager;
+class emu_timer;
+typedef struct _xml_data_node xml_data_node;
+class analog_field;
-/* opaque types pointing to live state */
-typedef struct _input_port_state input_port_state;
-typedef struct _input_field_state input_field_state;
-
+// constructor function pointer
+typedef void (*ioport_constructor)(device_t &owner, ioport_list &portlist, astring &errorbuf);
-/* forward declarations */
-class input_port_config;
-class input_field_config;
-class emu_timer;
+// I/O port callback function delegates
+typedef device_delegate<ioport_value (ioport_field &, void *)> ioport_field_read_delegate;
+typedef device_delegate<void (ioport_field &, void *, ioport_value, ioport_value)> ioport_field_write_delegate;
+typedef device_delegate<float (ioport_field &, float)> ioport_field_crossmap_delegate;
-/* template specializations */
-typedef tagged_list<input_port_config> ioport_list;
+// keyboard helper function delegates
+typedef delegate<int (const unicode_char *, size_t)> ioport_queue_chars_delegate;
+typedef delegate<bool (unicode_char)> ioport_accept_char_delegate;
+typedef delegate<bool ()> ioport_charqueue_empty_delegate;
-/* read input port callback function */
-typedef delegate<UINT32 (const input_field_config &, void *)> input_field_read_delegate;
+// ======================> inp_header
-/* input port write callback function */
-typedef delegate<void (const input_field_config &, void *, input_port_value, input_port_value)> input_field_write_delegate;
+// header at the front of INP files
+struct inp_header
+{
+ char header[8]; // +00: 8 byte header - must be "MAMEINP\0"
+ UINT64 basetime; // +08: base time of recording
+ UINT8 majversion; // +10: major INP version
+ UINT8 minversion; // +11: minor INP version
+ UINT8 reserved[2]; // +12: must be zero
+ char gamename[12]; // +14: game name string, NULL-terminated
+ char version[32]; // +20: system version string, NULL-terminated
+};
-/* crosshair mapping function */
-typedef delegate<float (const input_field_config &, float)> input_field_crossmap_delegate;
+// ======================> input_device_default
-/* encapsulates a condition on a port field or setting */
-typedef struct _input_condition input_condition;
-struct _input_condition
+// device defined default input settings
+struct input_device_default
{
- const char * tag; /* tag of port whose condition is to be tested */
- input_port_value mask; /* mask to apply to the port */
- input_port_value value; /* value to compare against */
- UINT8 condition; /* condition to use */
+ const char * tag; // tag of port to update
+ ioport_value mask; // mask to apply to the port
+ ioport_value defvalue; // new default value
};
-/* a single setting for a configuration or DIP switch */
-class input_setting_config
+// ======================> input_type_entry
+
+// describes a fundamental input type, including default input sequences
+class input_type_entry
{
- DISABLE_COPYING(input_setting_config);
- friend class simple_list<input_setting_config>;
+ friend class simple_list<input_type_entry>;
+ friend class ioport_manager;
public:
- input_setting_config(input_field_config &field, input_port_value value, const char *name);
- input_setting_config *next() const { return m_next; }
-
- input_port_value value; /* value of the bits in this setting */
- input_condition condition; /* condition under which this setting is valid */
- const char * name; /* user-friendly name to display */
+ // construction/destruction
+ input_type_entry(ioport_type type, ioport_group group, int player, const char *token, const char *name, input_seq standard);
+ input_type_entry(ioport_type type, ioport_group group, int player, const char *token, const char *name, input_seq standard, input_seq decrement, input_seq increment);
+ // getters
+ input_type_entry *next() const { return m_next; }
+ ioport_type type() const { return m_type; }
+ ioport_group group() const { return m_group; }
+ UINT8 player() const { return m_player; }
+ const char *token() const { return m_token; }
+ const char *name() const { return m_name; }
+ input_seq &defseq(input_seq_type seqtype = SEQ_TYPE_STANDARD) { return m_defseq[seqtype]; }
+ const input_seq &seq(input_seq_type seqtype = SEQ_TYPE_STANDARD) const { return m_seq[seqtype]; }
+
+ // setters
+ void configure_osd(const char *token, const char *name);
+
private:
- input_field_config & m_field; /* pointer back to the field that owns us */
- input_setting_config * m_next; /* pointer to next setting in sequence */
+ // internal state
+ input_type_entry * m_next; // next description in the list
+ ioport_type m_type; // IPT_* for this entry
+ ioport_group m_group; // which group the port belongs to
+ UINT8 m_player; // player number (0 is player 1)
+ const char * m_token; // token used to store settings
+ const char * m_name; // user-friendly name
+ input_seq m_defseq[SEQ_TYPE_TOTAL];// default input sequence
+ input_seq m_seq[SEQ_TYPE_TOTAL];// currently configured sequences
};
-/* a mapping from a bit to a physical DIP switch description */
-class input_field_diplocation
+// ======================> digital_joystick
+
+// tracking information about a digital joystick input
+class digital_joystick
{
- DISABLE_COPYING(input_field_diplocation);
- friend class simple_list<input_field_diplocation>;
+ DISABLE_COPYING(digital_joystick);
+ friend class simple_list<digital_joystick>;
public:
- input_field_diplocation(const char *string, UINT8 swnum, bool invert);
- input_field_diplocation *next() const { return m_next; }
-
- astring swname; /* name of the physical DIP switch */
- UINT8 swnum; /* physical switch number */
- bool invert; /* is this an active-high DIP? */
+ // directions
+ enum direction_t
+ {
+ JOYDIR_UP,
+ JOYDIR_DOWN,
+ JOYDIR_LEFT,
+ JOYDIR_RIGHT,
+ JOYDIR_COUNT
+ };
+
+ // bit constants
+ static const UINT8 UP_BIT = 1 << JOYDIR_UP;
+ static const UINT8 DOWN_BIT = 1 << JOYDIR_DOWN;
+ static const UINT8 LEFT_BIT = 1 << JOYDIR_LEFT;
+ static const UINT8 RIGHT_BIT = 1 << JOYDIR_RIGHT;
+ // construction/destruction
+ digital_joystick(int player, int number);
+
+ // getters
+ digital_joystick *next() const { return m_next; }
+ int player() const { return m_player; }
+ int number() const { return m_number; }
+ UINT8 current() const { return m_current; }
+ UINT8 current4way() const { return m_current4way; }
+
+ // configuration
+ direction_t set_axis(ioport_field &field);
+
+ // updates
+ void frame_update();
+
private:
- input_field_diplocation * m_next; /* pointer to the next bit */
+ // internal state
+ digital_joystick * m_next; // next joystick in the list
+ int m_player; // player number represented
+ int m_number; // joystick number represented
+ ioport_field * m_field[JOYDIR_COUNT]; // input field for each direction
+ UINT8 m_current; // current value
+ UINT8 m_current4way; // current 4-way value
+ UINT8 m_previous; // previous value
};
+DECLARE_ENUM_OPERATORS(digital_joystick::direction_t)
-/* a single bitfield within an input port */
-class input_field_config
+// ======================> natural_keyboard
+
+// buffer to handle copy/paste/insert of keys
+class natural_keyboard
{
- DISABLE_COPYING(input_field_config);
- friend class simple_list<input_field_config>;
+ DISABLE_COPYING(natural_keyboard);
public:
- input_field_config(input_port_config &port, int type, input_port_value defvalue, input_port_value maskbits, const char *name = NULL);
+ // construction/destruction
+ natural_keyboard(running_machine &machine);
+
+ // getters and queries
+ running_machine &machine() const { return m_machine; }
+ bool empty() const { return (m_bufbegin == m_bufend); }
+ bool full() const { return ((m_bufend + 1) % m_buffer.count()) == m_bufbegin; }
+ bool can_post() const { return (!m_queue_chars.isnull() || m_keycode_map.count() == 0); }
+ bool is_posting() const { return (!empty() || (!m_charqueue_empty.isnull() && !m_charqueue_empty())); }
- input_field_config *next() const { return m_next; }
- input_port_config &port() const { return m_port; }
- running_machine &machine() const;
- simple_list<input_setting_config> &settinglist() { return m_settinglist; }
- const simple_list<input_setting_config> &settinglist() const { return m_settinglist; }
- simple_list<input_field_diplocation> &diploclist() { return m_diploclist; }
- int modcount() const { return m_modcount; }
+ // configuration
+ void configure(ioport_queue_chars_delegate queue_chars, ioport_accept_char_delegate accept_char, ioport_charqueue_empty_delegate charqueue_empty);
- /* generally-applicable data */
- input_port_value mask; /* mask of bits belonging to the field */
- input_port_value defvalue; /* default value of these bits */
- input_condition condition; /* condition under which this field is relevant */
- UINT32 type; /* IPT_* type for this port */
- UINT8 player; /* player number (0-based) */
- UINT32 flags; /* combination of FIELD_FLAG_* and ANALOG_FLAG_* above */
- UINT8 impulse; /* number of frames before reverting to defvalue */
- const char * name; /* user-friendly name to display */
- input_seq seq[SEQ_TYPE_TOTAL];/* sequences of all types */
- input_field_read_delegate read; /* read callback routine */
- void * read_param; /* parameter for read callback routine */
- const char * read_device; /* parameter for read callback routine */
- input_field_write_delegate write; /* write callback routine */
- void * write_param; /* parameter for write callback routine */
- const char * write_device; /* parameter for write callback routine */
-
- /* data relevant to analog control types */
- INT32 min; /* minimum value for absolute axes */
- INT32 max; /* maximum value for absolute axes */
- INT32 sensitivity; /* sensitivity (100=normal) */
- INT32 delta; /* delta to apply each frame a digital inc/dec key is pressed */
- INT32 centerdelta; /* delta to apply each frame no digital inputs are pressed */
- UINT8 crossaxis; /* crosshair axis */
- double crossscale; /* crosshair scale */
- double crossoffset; /* crosshair offset */
- double crossaltaxis; /* crosshair alternate axis value */
- input_field_crossmap_delegate crossmapper; /* crosshair mapping function */
- const char * crossmapper_device; /* parameter for write callback routine */
- UINT16 full_turn_count;/* number of optical counts for 1 full turn of the original control */
- const input_port_value * remap_table; /* pointer to an array that remaps the port value */
-
- /* data relevant to other specific types */
- UINT8 way; /* digital joystick 2/4/8-way descriptions */
- unicode_char chars[3]; /* (MESS-specific) unicode key data */
-
- /* this field is only valid if the device is live */
- input_field_state * state; /* live state of field (NULL if not live) */
+ // posting
+ void post(unicode_char ch);
+ void post(const unicode_char *text, size_t length = 0, attotime rate = attotime::zero);
+ void post_utf8(const char *text, size_t length = 0, attotime rate = attotime::zero);
+ void post_coded(const char *text, size_t length = 0, attotime rate = attotime::zero);
+
+ void frame_update(ioport_port &port, ioport_value &digital);
+ const char *key_name(astring &string, unicode_char ch);
private:
- input_field_config * m_next; /* pointer to next field in sequence */
- input_port_config & m_port; /* pointer back to the port that owns us */
- int m_modcount;
- simple_list<input_setting_config> m_settinglist; /* list of input_setting_configs */
- simple_list<input_field_diplocation> m_diploclist; /* list of locations for various bits */
+ // internal keyboard code information
+ struct keycode_map_entry
+ {
+ unicode_char ch;
+ ioport_field * field[UCHAR_SHIFT_END + 1 - UCHAR_SHIFT_BEGIN];
+ };
+
+ // internal helpers
+ void build_codes(ioport_manager &manager);
+ bool can_post_directly(unicode_char ch);
+ bool can_post_alternate(unicode_char ch);
+ attotime choose_delay(unicode_char ch);
+ void internal_post(unicode_char ch);
+ void timer(void *ptr, int param);
+ const char *unicode_to_string(astring &buffer, unicode_char ch);
+ const keycode_map_entry *find_code(unicode_char ch) const;
+
+ // debugger helpers
+ static void execute_input(running_machine &machine, int ref, int params, const char *param[]);
+ static void execute_dumpkbd(running_machine &machine, int ref, int params, const char *param[]);
+
+ // internal state
+ running_machine & m_machine; // reference to our machine
+ UINT32 m_bufbegin; // index of starting character
+ UINT32 m_bufend; // index of ending character
+ dynamic_array<unicode_char> m_buffer; // actual buffer
+ bool m_status_keydown; // current keydown status
+ bool m_last_cr; // was the last char a CR?
+ emu_timer * m_timer; // timer for posting characters
+ attotime m_current_rate; // current rate for posting
+ ioport_queue_chars_delegate m_queue_chars; // queue characters callback
+ ioport_accept_char_delegate m_accept_char; // accept character callback
+ ioport_charqueue_empty_delegate m_charqueue_empty; // character queue empty callback
+ dynamic_array<keycode_map_entry> m_keycode_map; // keycode map
};
-/* user-controllable settings for a field */
-typedef struct _input_field_user_settings input_field_user_settings;
-struct _input_field_user_settings
-{
- input_port_value value; /* for DIP switches */
- input_seq seq[SEQ_TYPE_TOTAL];/* sequences of all types */
- INT32 sensitivity; /* for analog controls */
- INT32 delta; /* for analog controls */
- INT32 centerdelta; /* for analog controls */
- UINT8 reverse; /* for analog controls */
-};
+// ======================> ioport_condition
-/* device defined default input settings */
-typedef struct _input_device_default input_device_default;
-struct _input_device_default
+// encapsulates a condition on a port field or setting
+class ioport_condition
{
- const char * tag; /* tag of port to update */
- input_port_value mask; /* mask to apply to the port */
- input_port_value defvalue; /* new default value */
+public:
+ // condition types
+ enum condition_t
+ {
+ ALWAYS = 0,
+ EQUALS,
+ NOTEQUALS,
+ GREATERTHAN,
+ NOTGREATERTHAN,
+ LESSTHAN,
+ NOTLESSTHAN
+ };
+
+ // construction/destruction
+ ioport_condition() { reset(); }
+ ioport_condition(condition_t condition, const char *tag, ioport_value mask, ioport_value value) { set(condition, tag, mask, value); }
+
+ // getters
+ const char *tag() const { return m_tag; }
+
+ // operators
+ bool operator==(const ioport_condition &rhs) const { return (m_mask == rhs.m_mask && m_value == rhs.m_value && m_condition == rhs.m_condition && strcmp(m_tag, rhs.m_tag) == 0); }
+ bool eval(device_t &device) const;
+ bool none() const { return (m_condition == ALWAYS); }
+
+ // configuration
+ void reset() { set(ALWAYS, NULL, 0, 0); }
+ void set(condition_t condition, const char *tag, ioport_value mask, ioport_value value)
+ {
+ m_condition = condition;
+ m_tag = tag;
+ m_mask = mask;
+ m_value = value;
+ }
+
+private:
+ // internal state
+ condition_t m_condition; // condition to use
+ const char * m_tag; // tag of port whose condition is to be tested
+ ioport_value m_mask; // mask to apply to the port
+ ioport_value m_value; // value to compare against
};
-/* a single input port configuration */
-class input_port_config
+
+// ======================> ioport_setting
+
+// a single setting for a configuration or DIP switch
+class ioport_setting
{
- DISABLE_COPYING(input_port_config);
- friend class simple_list<input_port_config>;
+ DISABLE_COPYING(ioport_setting);
+ friend class simple_list<ioport_setting>;
public:
// construction/destruction
- input_port_config(device_t &owner, const char *tag);
-
+ ioport_setting(ioport_field &field, ioport_value value, const char *name);
+
// getters
- input_port_config *next() const { return m_next; }
- device_t &owner() const { return m_owner; }
+ ioport_setting *next() const { return m_next; }
+ ioport_field &field() const { return m_field; }
+ device_t &device() const;
running_machine &machine() const;
- input_field_config *first_field() const { return m_fieldlist.first(); }
- simple_list<input_field_config> &fieldlist() { return m_fieldlist; }
- const char *tag() const { return m_tag; }
- int modcount() const { return m_modcount; }
+ ioport_value value() const { return m_value; }
+ ioport_condition &condition() { return m_condition; }
+ const char *name() const { return m_name; }
- void bump_modcount() { m_modcount++; }
+ // helpers
+ bool enabled() { return m_condition.eval(device()); }
- void collapse_fields(astring &errorbuf);
+private:
+ // internal state
+ ioport_setting * m_next; // pointer to next setting in sequence
+ ioport_field & m_field; // pointer back to the field that owns us
+ ioport_value m_value; // value of the bits in this setting
+ const char * m_name; // user-friendly name to display
+ ioport_condition m_condition; // condition under which this setting is valid
+};
- /* these fields are only valid if the port is live */
- input_port_state * state; /* live state of port (NULL if not live) */
- input_port_value active; /* mask of active bits in the port */
+
+// ======================> ioport_diplocation
+
+// a mapping from a bit to a physical DIP switch description
+class ioport_diplocation
+{
+ DISABLE_COPYING(ioport_diplocation);
+ friend class simple_list<ioport_diplocation>;
+
+public:
+ // construction/destruction
+ ioport_diplocation(const char *name, UINT8 swnum, bool invert);
+
+ // getters
+ ioport_diplocation *next() const { return m_next; }
+ const char *name() const { return m_name; }
+ UINT8 number() const { return m_number; }
+ bool inverted() const { return m_invert; }
private:
- input_port_config * m_next; /* pointer to next port */
- device_t & m_owner; /* associated device, when appropriate */
- simple_list<input_field_config> m_fieldlist; /* list of input_field_configs */
- astring m_tag; /* pointer to this port's tag */
- int m_modcount;
+ ioport_diplocation * m_next; // pointer to the next bit
+ astring m_name; // name of the physical DIP switch
+ UINT8 m_number; // physical switch number
+ bool m_invert; // is this an active-high DIP?
};
-/* describes a fundamental input type, including default input sequences */
-class input_type_entry
+// ======================> ioport_field
+
+// a single bitfield within an input port
+class ioport_field
{
- friend class simple_list<input_type_entry>;
+ DISABLE_COPYING(ioport_field);
+ friend class simple_list<ioport_field>;
+ friend class ioport_configurer;
+ friend class dynamic_field;
+
+ // flags for ioport_fields
+ static const int FIELD_FLAG_UNUSED = 0x01; // set if this field is unused but relevant to other games on the same hw
+ static const int FIELD_FLAG_COCKTAIL = 0x02; // set if this field is relevant only for cocktail cabinets
+ static const int FIELD_FLAG_TOGGLE = 0x04; // set if this field should behave as a toggle
+ static const int FIELD_FLAG_ROTATED = 0x08; // set if this field represents a rotated control
+ static const int ANALOG_FLAG_REVERSE = 0x10; // analog only: reverse the sense of the axis
+ static const int ANALOG_FLAG_RESET = 0x20; // analog only: always preload in->default for relative axes, returning only deltas
+ static const int ANALOG_FLAG_WRAPS = 0x40; // analog only: positional count wraps around
+ static const int ANALOG_FLAG_INVERT = 0x80; // analog only: bitwise invert bits
public:
- input_type_entry(UINT32 type, ioport_group group, int player, const char *token, const char *name, input_seq standard);
- input_type_entry(UINT32 type, ioport_group group, int player, const char *token, const char *name, input_seq standard, input_seq decrement, input_seq increment);
-
- input_type_entry *next() const { return m_next; }
+ // construction/destruction
+ ioport_field(ioport_port &port, ioport_type type, ioport_value defvalue, ioport_value maskbits, const char *name = NULL);
+ ~ioport_field();
- UINT32 type; /* IPT_* for this entry */
- ioport_group group; /* which group the port belongs to */
- UINT8 player; /* player number (0 is player 1) */
- const char * token; /* token used to store settings */
- const char * name; /* user-friendly name */
- input_seq defseq[SEQ_TYPE_TOTAL];/* default input sequence */
- input_seq seq[SEQ_TYPE_TOTAL];/* currently configured sequences */
+ // getters
+ ioport_field *next() const { return m_next; }
+ ioport_port &port() const { return m_port; }
+ device_t &device() const;
+ ioport_manager &manager() const;
+ running_machine &machine() const;
+ int modcount() const { return m_modcount; }
+ ioport_setting *first_setting() const { return m_settinglist.first(); }
+ ioport_diplocation *first_diplocation() const { return m_diploclist.first(); }
+
+ ioport_value mask() const { return m_mask; }
+ ioport_value defvalue() const { return m_defvalue; }
+ ioport_condition &condition() { return m_condition; }
+ ioport_type type() const { return m_type; }
+ UINT8 player() const { return m_player + 1; }
+
+ bool unused() const { return ((m_flags & FIELD_FLAG_UNUSED) != 0); }
+ bool cocktail() const { return ((m_flags & FIELD_FLAG_COCKTAIL) != 0); }
+ bool toggle() const { return ((m_flags & FIELD_FLAG_TOGGLE) != 0); }
+ bool rotated() const { return ((m_flags & FIELD_FLAG_ROTATED) != 0); }
+ bool analog_reverse() const { return ((m_flags & ANALOG_FLAG_REVERSE) != 0); }
+ bool analog_reset() const { return ((m_flags & ANALOG_FLAG_RESET) != 0); }
+ bool analog_wraps() const { return ((m_flags & ANALOG_FLAG_WRAPS) != 0); }
+ bool analog_invert() const { return ((m_flags & ANALOG_FLAG_INVERT) != 0); }
+
+ UINT8 impulse() const { return m_impulse; }
+ const char *name() const;
+ const char *specific_name() const { return m_name; }
+ const input_seq &seq(input_seq_type seqtype = SEQ_TYPE_STANDARD) const;
+ bool has_dynamic_read() const { return !m_read.isnull(); }
+ bool has_dynamic_write() const { return !m_write.isnull(); }
+
+ ioport_value minval() const { return m_min; }
+ ioport_value maxval() const { return m_max; }
+ INT32 sensitivity() const { return m_sensitivity; }
+ INT32 delta() const { return m_delta; }
+ INT32 centerdelta() const { return m_centerdelta; }
+ crosshair_axis_t crosshair_axis() const { return m_crosshair_axis; }
+ double crosshair_scale() const { return m_crosshair_scale; }
+ double crosshair_offset() const { return m_crosshair_offset; }
+ UINT16 full_turn_count() const { return m_full_turn_count; }
+ const ioport_value *remap_table() const { return m_remap_table; }
+
+ UINT8 way() const { return m_way; }
+ unicode_char keyboard_code(int which) const;
+ ioport_field_live &live() const { assert(m_live != NULL); return *m_live; }
+
+ // setters
+ void set_crosshair_scale(double scale) { m_crosshair_scale = scale; }
+ void set_crosshair_offset(double offset) { m_crosshair_offset = offset; }
+
+ // derived getters
+ ioport_type_class type_class() const;
+ bool is_analog() const { return (m_type > IPT_ANALOG_FIRST && m_type < IPT_ANALOG_LAST); }
+ bool is_digital_joystick() const { return (m_type > IPT_DIGITAL_JOYSTICK_FIRST && m_type < IPT_DIGITAL_JOYSTICK_LAST); }
+
+ // additional operations
+ bool enabled() const { return m_condition.eval(device()); }
+ const char *setting_name() const;
+ bool has_previous_setting() const;
+ void select_previous_setting();
+ bool has_next_setting() const;
+ void select_next_setting();
+ void crosshair_position(float &x, float &y, bool &gotx, bool &goty);
+ void init_live_state(analog_field *analog);
+ void frame_update(ioport_value &result, bool mouse_down);
+ void reduce_mask(ioport_value bits_to_remove) { m_mask &= ~bits_to_remove; }
+
+ // user-controllable settings for a field
+ struct user_settings
+ {
+ ioport_value value; // for DIP switches
+ input_seq seq[SEQ_TYPE_TOTAL]; // sequences of all types
+ INT32 sensitivity; // for analog controls
+ INT32 delta; // for analog controls
+ INT32 centerdelta; // for analog controls
+ bool reverse; // for analog controls
+ };
+ void get_user_settings(user_settings &settings);
+ void set_user_settings(const user_settings &settings);
private:
- input_type_entry * m_next; /* next description in the list */
+ void expand_diplocation(const char *location, astring &errorbuf);
+
+ // internal state
+ ioport_field * m_next; // pointer to next field in sequence
+ ioport_port & m_port; // reference to the port that owns us
+ ioport_field_live * m_live; // live state of field (NULL if not live)
+ int m_modcount; // modification count
+ simple_list<ioport_setting> m_settinglist; // list of input_setting_configs
+ simple_list<ioport_diplocation> m_diploclist; // list of locations for various bits
+
+ // generally-applicable data
+ ioport_value m_mask; // mask of bits belonging to the field
+ ioport_value m_defvalue; // default value of these bits
+ ioport_condition m_condition; // condition under which this field is relevant
+ ioport_type m_type; // IPT_* type for this port
+ UINT8 m_player; // player number (0-based)
+ UINT32 m_flags; // combination of FIELD_FLAG_* and ANALOG_FLAG_* above
+ UINT8 m_impulse; // number of frames before reverting to defvalue
+ const char * m_name; // user-friendly name to display
+ input_seq m_seq[SEQ_TYPE_TOTAL];// sequences of all types
+ ioport_field_read_delegate m_read; // read callback routine
+ void * m_read_param; // parameter for read callback routine
+ ioport_field_write_delegate m_write; // write callback routine
+ void * m_write_param; // parameter for write callback routine
+
+ // data relevant to analog control types
+ ioport_value m_min; // minimum value for absolute axes
+ ioport_value m_max; // maximum value for absolute axes
+ INT32 m_sensitivity; // sensitivity (100=normal)
+ INT32 m_delta; // delta to apply each frame a digital inc/dec key is pressed
+ INT32 m_centerdelta; // delta to apply each frame no digital inputs are pressed
+ crosshair_axis_t m_crosshair_axis; // crosshair axis
+ double m_crosshair_scale; // crosshair scale
+ double m_crosshair_offset; // crosshair offset
+ double m_crosshair_altaxis;// crosshair alternate axis value
+ ioport_field_crossmap_delegate m_crosshair_mapper; // crosshair mapping function
+ UINT16 m_full_turn_count; // number of optical counts for 1 full turn of the original control
+ const ioport_value * m_remap_table; // pointer to an array that remaps the port value
+
+ // data relevant to other specific types
+ UINT8 m_way; // digital joystick 2/4/8-way descriptions
+ unicode_char m_chars[4]; // unicode key data
};
-/* header at the front of INP files */
-typedef struct _inp_header inp_header;
-struct _inp_header
+// ======================> ioport_list
+
+// class that holds a list of I/O ports
+class ioport_list : public tagged_list<ioport_port>
{
- char header[8]; /* +00: 8 byte header - must be "MAMEINP\0" */
- UINT64 basetime; /* +08: base time of recording */
- UINT8 majversion; /* +10: major INP version */
- UINT8 minversion; /* +11: minor INP version */
- UINT8 reserved[2]; /* +12: must be zero */
- char gamename[12]; /* +14: game name string, NULL-terminated */
- char version[32]; /* +20: system version string, NULL-terminated */
-};
+ DISABLE_COPYING(ioport_list);
+public:
+ // construction/destruction
+ ioport_list(resource_pool &pool = global_resource_pool())
+ : tagged_list<ioport_port>(pool) { }
-struct digital_joystick_state
-{
- const input_field_config * field[4]; /* input field for up, down, left, right respectively */
- UINT8 inuse; /* is this joystick used? */
- UINT8 current; /* current value */
- UINT8 current4way; /* current 4-way value */
- UINT8 previous; /* previous value */
+ using tagged_list<ioport_port>::append;
+ void append(device_t &device, astring &errorbuf);
};
-#define DIGITAL_JOYSTICKS_PER_PLAYER 3
-#define NUM_SIMUL_KEYS (UCHAR_SHIFT_END - UCHAR_SHIFT_BEGIN + 1)
-struct inputx_code
-{
- unicode_char ch;
- const input_field_config * field[NUM_SIMUL_KEYS];
-};
+// ======================> ioport_port
-struct key_buffer
+// a single input port configuration
+class ioport_port
{
- int begin_pos;
- int end_pos;
- unsigned int status_keydown : 1;
- int size;
- unicode_char *buffer;
+ DISABLE_COPYING(ioport_port);
+ friend class simple_list<ioport_port>;
+ friend class ioport_configurer;
+
+public:
+ // construction/destruction
+ ioport_port(device_t &owner, const char *tag);
+ ~ioport_port();
+
+ // getters
+ ioport_port *next() const { return m_next; }
+ ioport_manager &manager() const;
+ device_t &device() const { return m_device; }
+ running_machine &machine() const;
+ ioport_field *first_field() const { return m_fieldlist.first(); }
+ const char *tag() const { return m_tag; }
+ int modcount() const { return m_modcount; }
+ ioport_value active() const { return m_active; }
+ ioport_value active_safe(ioport_value defval) const { return (this == NULL) ? defval : active(); }
+ ioport_port_live &live() const { assert(m_live != NULL); return *m_live; }
+
+ // read/write to the port
+ ioport_value read();
+ ioport_value read_safe(ioport_value defval) { return (this == NULL) ? defval : read(); }
+ void write(ioport_value value, ioport_value mask = ~0);
+ void write_safe(ioport_value value, ioport_value mask = ~0) { if (this != NULL) write(value, mask); }
+
+ // other operations
+ ioport_field *field(ioport_value mask);
+ void collapse_fields(astring &errorbuf);
+ void frame_update(ioport_field *mouse_field);
+ void init_live_state();
+
+private:
+ void insert_field(ioport_field &newfield, ioport_value &disallowedbits, astring &errorbuf);
+
+ // internal state
+ ioport_port * m_next; // pointer to next port
+ device_t & m_device; // associated device
+ simple_list<ioport_field> m_fieldlist; // list of ioport_fields
+ astring m_tag; // copy of this port's tag
+ int m_modcount; // modification count
+ ioport_value m_active; // mask of active bits in the port
+ ioport_port_live * m_live; // live state of port (NULL if not live)
};
-/* private input port state */
+
+// ======================> ioport_manager
+
+// private input port state
class ioport_manager
{
+ DISABLE_COPYING(ioport_manager);
friend class device_t;
+ friend class ioport_configurer;
public:
// construction/destruction
@@ -929,368 +1235,406 @@ public:
// getters
running_machine &machine() const { return m_machine; }
- input_port_config *first_port() const { return m_portlist.first(); }
-
- /* global state */
- UINT8 safe_to_read; /* clear at start; set after state is loaded */
-
- /* types */
- simple_list<input_type_entry> typelist; /* list of live type states */
- input_type_entry * type_to_entry[__ipt_max][MAX_PLAYERS]; /* map from type/player to type state */
-
- /* specific special global input states */
- digital_joystick_state joystick_info[MAX_PLAYERS][DIGITAL_JOYSTICKS_PER_PLAYER]; /* joystick states */
-
- /* frame time tracking */
- attotime last_frame_time; /* time of the last frame callback */
- attoseconds_t last_delta_nsec; /* nanoseconds that passed since the previous callback */
-
- /* playback/record information */
- emu_file * record_file; /* recording file (NULL if not recording) */
- emu_file * playback_file; /* playback file (NULL if not recording) */
- UINT64 playback_accumulated_speed;/* accumulated speed during playback */
- UINT32 playback_accumulated_frames;/* accumulated frames during playback */
-
- /* inputx */
- inputx_code *codes;
- key_buffer keybuffer;
- emu_timer *inputx_timer;
- int (*queue_chars)(running_machine &machine, const unicode_char *text, size_t text_len);
- int (*accept_char)(running_machine &machine, unicode_char ch);
- int (*charqueue_empty)(running_machine &machine);
- attotime current_rate;
+ ioport_port *first_port() const { return m_portlist.first(); }
+ bool safe_to_read() const { return m_safe_to_read; }
+ natural_keyboard &natkeyboard() { return m_natkeyboard; }
+
+ // type helpers
+ input_type_entry *first_type() const { return m_typelist.first(); }
+ bool type_pressed(ioport_type type, int player = 0);
+ const char *type_name(ioport_type type, UINT8 player);
+ ioport_group type_group(ioport_type type, int player);
+ const input_seq &type_seq(ioport_type type, int player = 0, input_seq_type seqtype = SEQ_TYPE_STANDARD);
+ void set_type_seq(ioport_type type, int player, input_seq_type seqtype, const input_seq &newseq);
+ static bool type_is_analog(ioport_type type) { return (type > IPT_ANALOG_FIRST && type < IPT_ANALOG_LAST); }
+ bool type_class_present(ioport_type_class inputclass);
+
+ // other helpers
+ digital_joystick &digjoystick(int player, int joysticknum);
+ int count_players() const;
+ bool crosshair_position(int player, float &x, float &y);
+ bool has_keyboard() const;
+ void setup_natural_keyboard(ioport_queue_chars_delegate queue_chars, ioport_accept_char_delegate accept_char, ioport_charqueue_empty_delegate charqueue_empty);
+ ioport_value frame_interpolate(ioport_value oldval, ioport_value newval);
+ ioport_type token_to_input_type(const char *string, int &player) const;
+ const char *input_type_to_token(astring &string, ioport_type type, int player);
+ void frame_update();
private:
- input_port_config *port(const char *tag) const { return m_portlist.find(tag); }
-
- // internals
- ioport_list m_portlist; // points to a list of input port configurations
+ // internal helpers
+ void init_port_types();
+ void init_autoselect_devices(int type1, int type2, int type3, const char *option, const char *ananame);
+
+ ioport_port *port(const char *tag) const { return m_portlist.find(tag); }
+ void exit();
+ input_seq_type token_to_seq_type(const char *string);
+ void update_defaults();
+
+ void load_config(int config_type, xml_data_node *parentnode);
+ void load_remap_table(xml_data_node *parentnode);
+ bool load_default_config(xml_data_node *portnode, int type, int player, const input_seq *newseq);
+ bool load_game_config(xml_data_node *portnode, int type, int player, const input_seq *newseq);
+
+ void save_config(int config_type, xml_data_node *parentnode);
+ void save_sequence(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);
+
+ template<typename _Type> _Type playback_read(_Type &result);
+ time_t playback_init();
+ void playback_end(const char *message = NULL);
+ void playback_frame(attotime curtime);
+ void playback_port(ioport_port &port);
+
+ template<typename _Type> void record_write(_Type value);
+ void record_init();
+ void record_end(const char *message = NULL);
+ void record_frame(attotime curtime);
+ void record_port(ioport_port &port);
// internal state
- running_machine & m_machine;
+ running_machine & m_machine; // reference to owning machine
+ bool m_safe_to_read; // clear at start; set after state is loaded
+ ioport_list m_portlist; // list of input port configurations
+
+ // types
+ simple_list<input_type_entry> m_typelist; // list of live type states
+ input_type_entry * m_type_to_entry[IPT_COUNT][MAX_PLAYERS]; // map from type/player to type state
+
+ // specific special global input states
+ simple_list<digital_joystick> m_joystick_list; // list of digital joysticks
+ natural_keyboard m_natkeyboard; // natural keyboard support
+
+ // frame time tracking
+ attotime m_last_frame_time; // time of the last frame callback
+ attoseconds_t m_last_delta_nsec; // nanoseconds that passed since the previous callback
+
+ // playback/record information
+ emu_file m_record_file; // recording file (NULL if not recording)
+ emu_file m_playback_file; // playback file (NULL if not recording)
+ UINT64 m_playback_accumulated_speed; // accumulated speed during playback
+ UINT32 m_playback_accumulated_frames; // accumulated frames during playback
};
-/***************************************************************************
- MACROS
-***************************************************************************/
+// ======================> ioport_configurer
-/* macro for a read callback function (PORT_CUSTOM) */
-#define CUSTOM_INPUT(name) input_port_value name(device_t &device, const input_field_config &field, void *param)
-#define CUSTOM_INPUT_MEMBER(name) input_port_value name(const input_field_config &field, void *param)
-#define DECLARE_CUSTOM_INPUT_MEMBER(name) input_port_value name(const input_field_config &field, void *param)
+// class to wrap helper functions
+class ioport_configurer
+{
+public:
+ // construction/destruction
+ ioport_configurer(device_t &owner, ioport_list &portlist, astring &errorbuf);
+
+ // static helpers
+ static const char *string_from_token(const char *string);
+
+ // port helpers
+ void port_alloc(const char *tag);
+ void port_modify(const char *tag);
+
+ // field helpers
+ void field_alloc(ioport_type type, ioport_value defval, ioport_value mask, const char *name = NULL);
+ void field_add_char(unicode_char ch);
+ void field_add_code(input_seq_type which, input_code code);
+ void field_set_way(int way) const { m_curfield->m_way = way; }
+ void field_set_rotated() const { m_curfield->m_flags |= ioport_field::FIELD_FLAG_ROTATED; }
+ void field_set_name(const char *name) const { m_curfield->m_name = string_from_token(name); }
+ void field_set_player(int player) const { m_curfield->m_player = player - 1; }
+ void field_set_cocktail() const { m_curfield->m_flags |= ioport_field::FIELD_FLAG_COCKTAIL; field_set_player(2); }
+ void field_set_toggle() const { m_curfield->m_flags |= ioport_field::FIELD_FLAG_TOGGLE; }
+ void field_set_impulse(UINT8 impulse) const { m_curfield->m_impulse = impulse; }
+ void field_set_analog_reverse() const { m_curfield->m_flags |= ioport_field::ANALOG_FLAG_REVERSE; }
+ void field_set_analog_reset() const { m_curfield->m_flags |= ioport_field::ANALOG_FLAG_RESET; }
+ void field_set_unused() const { m_curfield->m_flags |= ioport_field::FIELD_FLAG_UNUSED; }
+ void field_set_min_max(ioport_value minval, ioport_value maxval) const { m_curfield->m_min = minval; m_curfield->m_max = maxval; }
+ void field_set_sensitivity(INT32 sensitivity) const { m_curfield->m_sensitivity = sensitivity; }
+ void field_set_delta(INT32 delta) const { m_curfield->m_centerdelta = m_curfield->m_delta = delta; }
+ void field_set_centerdelta(INT32 delta) const { m_curfield->m_centerdelta = delta; }
+ void field_set_crosshair(crosshair_axis_t axis, double altaxis, double scale, double offset) const { m_curfield->m_crosshair_axis = axis; m_curfield->m_crosshair_altaxis = altaxis; m_curfield->m_crosshair_scale = scale; m_curfield->m_crosshair_offset = offset; }
+ void field_set_crossmapper(ioport_field_crossmap_delegate callback) const { m_curfield->m_crosshair_mapper = callback; }
+ void field_set_full_turn_count(UINT16 count) const { m_curfield->m_full_turn_count = count; }
+ void field_set_analog_wraps() const { m_curfield->m_flags |= ioport_field::ANALOG_FLAG_WRAPS; }
+ void field_set_remap_table(const ioport_value *table) { m_curfield->m_remap_table = table; }
+ void field_set_analog_invert() const { m_curfield->m_flags |= ioport_field::ANALOG_FLAG_INVERT; }
+ void field_set_dynamic_read(ioport_field_read_delegate delegate, void *param = NULL) const { m_curfield->m_read = delegate; m_curfield->m_read_param = param; }
+ void field_set_dynamic_write(ioport_field_write_delegate delegate, void *param = NULL) const { m_curfield->m_write = delegate; m_curfield->m_write_param = param; }
+ void field_set_diplocation(const char *location) const { m_curfield->expand_diplocation(location, m_errorbuf); }
+
+ // setting helpers
+ void setting_alloc(ioport_value value, const char *name);
+
+ // misc helpers
+ void set_condition(ioport_condition::condition_t condition, const char *tag, ioport_value mask, ioport_value value);
+ void onoff_alloc(const char *name, ioport_value defval, ioport_value mask, const char *diplocation);
-/* macro for port write callback functions (PORT_CHANGED) */
-#define INPUT_CHANGED(name) void name(device_t &device, const input_field_config &field, void *param, input_port_value oldval, input_port_value newval)
-#define INPUT_CHANGED_MEMBER(name) void name(const input_field_config &field, void *param, input_port_value oldval, input_port_value newval)
-#define DECLARE_INPUT_CHANGED_MEMBER(name) void name(const input_field_config &field, void *param, input_port_value oldval, input_port_value newval)
+private:
+ // internal state
+ device_t & m_owner;
+ ioport_list & m_portlist;
+ astring & m_errorbuf;
+
+ ioport_port * m_curport;
+ ioport_field * m_curfield;
+ ioport_setting * m_cursetting;
+};
-/* macro for port changed callback functions (PORT_CROSSHAIR_MAPPER) */
-#define CROSSHAIR_MAPPER(name) float name(device_t &device, const input_field_config &field, float linear_value)
-#define CROSSHAIR_MAPPER_MEMBER(name) float name(const input_field_config &field, float linear_value)
-#define DECLARE_CROSSHAIR_MAPPER_MEMBER(name) float name(const input_field_config &field, float linear_value)
-/* macro for wrapping a default string */
-#define DEF_STR(str_num) ((const char *)INPUT_STRING_##str_num)
+//**************************************************************************
+// MACROS
+//**************************************************************************
-template<int (*_FunctionPointer)(device_t *)>
-input_port_value ioport_read_line_wrapper(device_t &device, const input_field_config &field, void *param)
-{
- return (*_FunctionPointer)(&device);
-}
+#define UCHAR_MAMEKEY(code) (UCHAR_MAMEKEY_BEGIN + ITEM_ID_##code)
-template<class _FunctionClass, int (_FunctionClass::*_FunctionPointer)()>
-input_port_value ioport_read_line_wrapper(_FunctionClass &device, const input_field_config &field, void *param)
-{
- return (device.*_FunctionPointer)();
-}
+// macro for a read callback function (PORT_CUSTOM)
+#define CUSTOM_INPUT(name) ioport_value name(device_t &device, ioport_field &field, void *param)
+#define CUSTOM_INPUT_MEMBER(name) ioport_value name(ioport_field &field, void *param)
+#define DECLARE_CUSTOM_INPUT_MEMBER(name) ioport_value name(ioport_field &field, void *param)
-template<void (*_FunctionPointer)(device_t *, int)>
-void ioport_write_line_wrapper(device_t &device, const input_field_config &field, void *param, input_port_value oldval, input_port_value newval)
-{
- return (*_FunctionPointer)(&device, newval);
-}
+// macro for port write callback functions (PORT_CHANGED)
+#define INPUT_CHANGED(name) void name(device_t &device, ioport_field &field, void *param, ioport_value oldval, ioport_value newval)
+#define INPUT_CHANGED_MEMBER(name) void name(ioport_field &field, void *param, ioport_value oldval, ioport_value newval)
+#define DECLARE_INPUT_CHANGED_MEMBER(name) void name(ioport_field &field, void *param, ioport_value oldval, ioport_value newval)
-template<class _FunctionClass, void (_FunctionClass::*_FunctionPointer)(int)>
-void ioport_write_line_wrapper(_FunctionClass &device, const input_field_config &field, void *param, input_port_value oldval, input_port_value newval)
-{
- return (device.*_FunctionPointer)(newval);
-}
+// macro for port changed callback functions (PORT_CROSSHAIR_MAPPER)
+#define CROSSHAIR_MAPPER(name) float name(device_t &device, ioport_field &field, float linear_value)
+#define CROSSHAIR_MAPPER_MEMBER(name) float name(ioport_field &field, float linear_value)
+#define DECLARE_CROSSHAIR_MAPPER_MEMBER(name) float name(ioport_field &field, float linear_value)
+// macro for wrapping a default string
+#define DEF_STR(str_num) ((const char *)INPUT_STRING_##str_num)
-/***************************************************************************
- MACROS FOR BUILDING INPUT PORTS
-***************************************************************************/
-typedef void (*ioport_constructor)(device_t &owner, ioport_list &portlist, astring &errorbuf);
+//**************************************************************************
+// MACROS FOR BUILDING INPUT PORTS
+//**************************************************************************
-/* so that "0" can be used for unneeded input ports */
+// so that "0" can be used for unneeded input ports
#define construct_ioport_0 NULL
-/* name of table */
+// name of table
#define INPUT_PORTS_NAME(_name) construct_ioport_##_name
-/* start of table */
+// start of table
#define INPUT_PORTS_START(_name) \
ATTR_COLD void INPUT_PORTS_NAME(_name)(device_t &owner, ioport_list &portlist, astring &errorbuf) \
{ \
- astring fulltag; \
- input_setting_config *cursetting = NULL; \
- input_field_config *curfield = NULL; \
- input_port_config *curport = NULL; \
- input_port_value maskbits = 0; \
- (void)cursetting; (void)curfield; (void)curport; (void)maskbits; \
-
-/* end of table */
+ ioport_configurer configurer(owner, portlist, errorbuf); \
+
+// end of table
#define INPUT_PORTS_END \
}
-/* aliasing */
+// aliasing
#define INPUT_PORTS_EXTERN(_name) \
extern void INPUT_PORTS_NAME(_name)(device_t &owner, ioport_list &portlist, astring &errorbuf)
-/* including */
+// including
#define PORT_INCLUDE(_name) \
INPUT_PORTS_NAME(_name)(owner, portlist, errorbuf); \
-/* start of a new input port (with included tag) */
+// start of a new input port (with included tag)
#define PORT_START(_tag) \
- curport = ioconfig_alloc_port(portlist, owner, _tag); \
- curfield = NULL; \
- cursetting = NULL; \
- maskbits = 0; \
+ configurer.port_alloc(_tag); \
-/* modify an existing port */
+// modify an existing port
#define PORT_MODIFY(_tag) \
- curport = ioconfig_modify_port(portlist, owner, _tag); \
- curfield = NULL; \
- cursetting = NULL; \
- maskbits = 0; \
+ configurer.port_modify(_tag); \
-/* input bit definition */
+// input bit definition
#define PORT_BIT(_mask, _default, _type) \
- curfield = ioconfig_alloc_field(*curport, (_type), (_default), (_mask)); \
- cursetting = NULL;
+ configurer.field_alloc((_type), (_default), (_mask)); \
-#define PORT_SPECIAL_ONOFF(_mask, _default, _strindex) PORT_SPECIAL_ONOFF_DIPLOC(_mask, _default, _strindex, NULL)
+#define PORT_SPECIAL_ONOFF(_mask, _default, _strindex) \
+ PORT_SPECIAL_ONOFF_DIPLOC(_mask, _default, _strindex, NULL)
#define PORT_SPECIAL_ONOFF_DIPLOC(_mask, _default, _strindex, _diploc) \
- curfield = ioconfig_alloc_onoff(*curport, DEF_STR(_strindex), _default, _mask, _diploc, errorbuf); \
- cursetting = NULL;
+ configurer.onoff_alloc(DEF_STR(_strindex), _default, _mask, _diploc); \
-/* append a code */
+// append a code
#define PORT_CODE(_code) \
- ioconfig_add_code(*curfield, SEQ_TYPE_STANDARD, _code);
+ configurer.field_add_code(SEQ_TYPE_STANDARD, _code);
#define PORT_CODE_DEC(_code) \
- ioconfig_add_code(*curfield, SEQ_TYPE_DECREMENT, _code);
+ configurer.field_add_code(SEQ_TYPE_DECREMENT, _code);
#define PORT_CODE_INC(_code) \
- ioconfig_add_code(*curfield, SEQ_TYPE_INCREMENT, _code);
+ configurer.field_add_code(SEQ_TYPE_INCREMENT, _code);
-/* joystick flags */
+// joystick flags
#define PORT_2WAY \
- curfield->way = 2;
+ configurer.field_set_way(2);
#define PORT_4WAY \
- curfield->way = 4;
+ configurer.field_set_way(4);
#define PORT_8WAY \
- curfield->way = 8;
+ configurer.field_set_way(8);
#define PORT_16WAY \
- curfield->way = 16;
+ configurer.field_set_way(16);
#define PORT_ROTATED \
- curfield->flags |= FIELD_FLAG_ROTATED
+ configurer.field_set_rotated();
-/* general flags */
+// general flags
#define PORT_NAME(_name) \
- curfield->name = input_port_string_from_token(_name);
+ configurer.field_set_name(_name);
#define PORT_PLAYER(_player) \
- curfield->player = (_player) - 1;
+ configurer.field_set_player(_player);
#define PORT_COCKTAIL \
- curfield->flags |= FIELD_FLAG_COCKTAIL; \
- curfield->player = 1;
+ configurer.field_set_cocktail();
#define PORT_TOGGLE \
- curfield->flags |= FIELD_FLAG_TOGGLE;
+ configurer.field_set_toggle();
#define PORT_IMPULSE(_duration) \
- curfield->impulse = _duration;
+ configurer.field_set_impulse(_duration);
#define PORT_REVERSE \
- curfield->flags |= ANALOG_FLAG_REVERSE;
+ configurer.field_set_analog_reverse();
#define PORT_RESET \
- curfield->flags |= ANALOG_FLAG_RESET;
+ configurer.field_set_analog_reset();
#define PORT_UNUSED \
- curfield->flags |= FIELD_FLAG_UNUSED;
+ configurer.field_set_unused();
-/* analog settings */
-/* if this macro is not used, the minimum defaluts to 0 and maximum defaults to the mask value */
+// analog settings
+// if this macro is not used, the minimum defaluts to 0 and maximum defaults to the mask value
#define PORT_MINMAX(_min, _max) \
- curfield->min = _min; \
- curfield->max = _max;
+ configurer.field_set_min_max(_min, _max);
#define PORT_SENSITIVITY(_sensitivity) \
- curfield->sensitivity = _sensitivity;
+ configurer.field_set_sensitivity(_sensitivity);
#define PORT_KEYDELTA(_delta) \
- curfield->delta = curfield->centerdelta = _delta;
+ configurer.field_set_delta(_delta); \
-/* note that PORT_CENTERDELTA must appear after PORT_KEYDELTA */
+// note that PORT_CENTERDELTA must appear after PORT_KEYDELTA
#define PORT_CENTERDELTA(_delta) \
- curfield->centerdelta = _delta;
+ configurer.field_set_centerdelta(_delta);
#define PORT_CROSSHAIR(axis, scale, offset, altaxis) \
- curfield->crossaxis = CROSSHAIR_AXIS_##axis; \
- curfield->crossaltaxis = altaxis; \
- curfield->crossscale = scale; \
- curfield->crossoffset = offset;
+ configurer.field_set_crosshair(CROSSHAIR_AXIS_##axis, altaxis, scale, offset);
#define PORT_CROSSHAIR_MAPPER(_callback) \
- curfield->crossmapper = input_field_crossmap_delegate(_callback, #_callback, (device_t *)NULL); \
- curfield->crossmapper_device = DEVICE_SELF;
+ configurer.field_set_crossmapper(ioport_field_crossmap_delegate(_callback, #_callback, DEVICE_SELF, (device_t *)NULL));
#define PORT_CROSSHAIR_MAPPER_MEMBER(_device, _class, _member) \
- curfield->crossmapper = input_field_crossmap_delegate(&_class::_member, #_class "::" #_member, (_class *)NULL); \
- curfield->crossmapper_device = _device;
+ configurer.field_set_crossmapper(ioport_field_crossmap_delegate(&_class::_member, #_class "::" #_member, _device, (_class *)NULL));
-/* how many optical counts for 1 full turn of the control */
+// how many optical counts for 1 full turn of the control
#define PORT_FULL_TURN_COUNT(_count) \
- curfield->full_turn_count = _count;
+ configurer.field_set_full_turn_count(_count);
-/* positional controls can be binary or 1 of X */
-/* 1 of X not completed yet */
-/* if it is specified as PORT_REMAP_TABLE then it is binary, but remapped */
-/* otherwise it is binary */
+// positional controls can be binary or 1 of X
+// 1 of X not completed yet
+// if it is specified as PORT_REMAP_TABLE then it is binary, but remapped
+// otherwise it is binary
#define PORT_POSITIONS(_positions) \
- curfield->max = _positions;
+ configurer.field_set_min_max(0, _positions);
-/* positional control wraps at min/max */
+// positional control wraps at min/max
#define PORT_WRAPS \
- curfield->flags |= ANALOG_FLAG_WRAPS;
+ configurer.field_set_analog_wraps();
-/* positional control uses this remap table */
+// positional control uses this remap table
#define PORT_REMAP_TABLE(_table) \
- curfield->remap_table = _table;
+ configurer.field_set_remap_table(_table);
-/* positional control bits are active low */
+// positional control bits are active low
#define PORT_INVERT \
- curfield->flags |= ANALOG_FLAG_INVERT;
+ configurer.field_set_analog_invert();
-/* read callbacks */
+// read callbacks
#define PORT_CUSTOM(_callback, _param) \
- curfield->read = input_field_read_delegate(_callback, #_callback, (device_t *)NULL); \
- curfield->read_param = (void *)(_param); \
- curfield->read_device = DEVICE_SELF;
+ configurer.field_set_dynamic_read(ioport_field_read_delegate(_callback, #_callback, DEVICE_SELF, (device_t *)NULL), (void *)(_param));
#define PORT_CUSTOM_MEMBER(_device, _class, _member, _param) \
- curfield->read = input_field_read_delegate(&_class::_member, #_class "::" #_member, (_class *)NULL); \
- curfield->read_param = (void *)(_param); \
- curfield->read_device = (_device);
+ configurer.field_set_dynamic_read(ioport_field_read_delegate(&_class::_member, #_class "::" #_member, _device, (_class *)NULL), (void *)(_param));
-/* write callbacks */
+// write callbacks
#define PORT_CHANGED(_callback, _param) \
- curfield->write = input_field_write_delegate(_callback, #_callback, (device_t *)NULL); \
- curfield->write_param = (void *)(_param); \
- curfield->write_device = DEVICE_SELF;
+ configurer.field_set_dynamic_write(ioport_field_write_delegate(_callback, #_callback, DEVICE_SELF, (device_t *)NULL), (void *)(_param));
#define PORT_CHANGED_MEMBER(_device, _class, _member, _param) \
- curfield->write = input_field_write_delegate(&_class::_member, #_class "::" #_member, (_class *)NULL); \
- curfield->write_param = (void *)(_param); \
- curfield->write_device = (_device);
+ configurer.field_set_dynamic_write(ioport_field_write_delegate(&_class::_member, #_class "::" #_member, _device, (_class *)NULL), (void *)(_param));
-/* input device handler */
+// input device handler
#define PORT_READ_LINE_DEVICE(_device, _read_line_device) \
- curfield->read = input_field_read_delegate(&ioport_read_line_wrapper<_read_line_device>, #_read_line_device, (device_t *)NULL); \
- curfield->read_param = NULL; \
- curfield->read_device = _device;
+ configurer.field_set_dynamic_read(ioport_field_read_delegate(&ioport_read_line_wrapper<_read_line_device>, #_read_line_device, _device, (device_t *)NULL));
#define PORT_READ_LINE_DEVICE_MEMBER(_device, _class, _member) \
- curfield->read = input_field_read_delegate(&ioport_read_line_wrapper<_class, &_class::_member>, #_class "::" #_member, (_class *)NULL); \
- curfield->read_param = NULL; \
- curfield->read_device = _device;
+ configurer.field_set_dynamic_read(ioport_field_read_delegate(&ioport_read_line_wrapper<_class, &_class::_member>, #_class "::" #_member, _device, (_class *)NULL));
-/* output device handler */
+// output device handler
#define PORT_WRITE_LINE_DEVICE(_device, _write_line_device) \
- curfield->write = input_field_write_delegate(&ioport_write_line_wrapper<_write_line_device>, #_write_line_device, (device_t *)NULL); \
- curfield->write_param = NULL; \
- curfield->write_device = _device;
+ configurer.field_set_dynamic_write(ioport_field_write_delegate(&ioport_write_line_wrapper<_write_line_device>, #_write_line_device, _device, (device_t *)NULL));
#define PORT_WRITE_LINE_DEVICE_MEMBER(_device, _class, _member) \
- curfield->write = input_field_write_delegate(&ioport_write_line_wrapper<_class, &_class::_member>, #_class "::" #_member, (_class *)NULL); \
- curfield->write_param = NULL; \
- curfield->write_device = _device;
+ configurer.field_set_dynamic_write(ioport_field_write_delegate(&ioport_write_line_wrapper<_class, &_class::_member>, #_class "::" #_member, _device, (_class *)NULL));
-/* dip switch definition */
+// dip switch definition
#define PORT_DIPNAME(_mask, _default, _name) \
- curfield = ioconfig_alloc_field(*curport, IPT_DIPSWITCH, (_default), (_mask), (_name)); \
- cursetting = NULL;
+ configurer.field_alloc(IPT_DIPSWITCH, (_default), (_mask), (_name)); \
#define PORT_DIPSETTING(_default, _name) \
- cursetting = ioconfig_alloc_setting(*curfield, (_default) & curfield->mask, (_name));
+ configurer.setting_alloc((_default), (_name)); \
-/* physical location, of the form: name:[!]sw,[name:][!]sw,... */
-/* note that these are specified LSB-first */
+// physical location, of the form: name:[!]sw,[name:][!]sw,...
+// note that these are specified LSB-first
#define PORT_DIPLOCATION(_location) \
- diplocation_list_alloc(*curfield, _location, errorbuf);
+ configurer.field_set_diplocation(_location); \
-/* conditionals for dip switch settings */
+// conditionals for dip switch settings
#define PORT_CONDITION(_tag, _mask, _condition, _value) \
-{ \
- input_condition &condition = (cursetting != NULL) ? cursetting->condition : curfield->condition; \
- condition.tag = (_tag); \
- condition.mask = (_mask); \
- condition.condition = (_condition); \
- condition.value = (_value); \
-}
+ configurer.set_condition(ioport_condition::_condition, _tag, _mask, _value); \
-/* analog adjuster definition */
+// analog adjuster definition
#define PORT_ADJUSTER(_default, _name) \
- curfield = ioconfig_alloc_field(*curport, IPT_ADJUSTER, (_default), 0xff, (_name)); \
- cursetting = NULL; \
+ configurer.field_alloc(IPT_ADJUSTER, (_default), 0xff, (_name)); \
-/* config definition */
+// config definition
#define PORT_CONFNAME(_mask, _default, _name) \
- curfield = ioconfig_alloc_field(*curport, IPT_CONFIG, (_default), (_mask), (_name)); \
- cursetting = NULL; \
+ configurer.field_alloc(IPT_CONFIG, (_default), (_mask), (_name)); \
#define PORT_CONFSETTING(_default, _name) \
- cursetting = ioconfig_alloc_setting(*curfield, (_default) & curfield->mask, (_name));
+ configurer.setting_alloc((_default), (_name));
-/* keyboard chars */
+// keyboard chars
#define PORT_CHAR(_ch) \
- ioconfig_field_add_char(*curfield, _ch, errorbuf);
+ configurer.field_add_char(_ch);
-/* name of table */
+// name of table
#define DEVICE_INPUT_DEFAULTS_NAME(_name) device_iptdef_##_name
#define device_iptdef_0 NULL
#define device_iptdef___null NULL
-/* start of table */
+// start of table
#define DEVICE_INPUT_DEFAULTS_START(_name) \
const input_device_default DEVICE_INPUT_DEFAULTS_NAME(_name)[] = {
-/* end of table */
+// end of table
#define DEVICE_INPUT_DEFAULTS(_tag,_mask,_defval) \
{ _tag ,_mask, _defval }, \
-/* end of table */
+// end of table
#define DEVICE_INPUT_DEFAULTS_END \
{NULL,0,0} };
-/***************************************************************************
- HELPER MACROS
-***************************************************************************/
+
+
+//**************************************************************************
+// HELPER MACROS
+//**************************************************************************
#define PORT_DIPUNUSED_DIPLOC(_mask, _default, _diploc) \
PORT_SPECIAL_ONOFF_DIPLOC(_mask, _default, Unused, _diploc)
@@ -1313,181 +1657,51 @@ ATTR_COLD void INPUT_PORTS_NAME(_name)(device_t &owner, ioport_list &portlist, a
#define PORT_SERVICE_NO_TOGGLE(_mask, _default) \
PORT_BIT( _mask, _mask & _default, IPT_SERVICE ) PORT_NAME( DEF_STR( Service_Mode ))
+#define PORT_VBLANK(_screen) \
+ PORT_READ_LINE_DEVICE_MEMBER(_screen, screen_device, vblank_port_read)
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
-
-
-/* ----- port configurations ----- */
-
-/* initialize an input port list structure and allocate ports according to the given tokens */
-void input_port_list_init(device_t &device, ioport_list &portlist, astring &errorbuf);
-
-/* return the field that matches the given tag and mask */
-const input_field_config *input_field_by_tag_and_mask(running_machine &machine, const char *tag, input_port_value mask);
-
-
-
-/* ----- accessors for input types ----- */
-
-/* return TRUE if the given type represents an analog control */
-int input_type_is_analog(int type);
-
-/* return the name for the given type/player */
-const char *input_type_name(running_machine &machine, int type, int player);
-
-/* return the group for the given type/player */
-int input_type_group(running_machine &machine, int type, int player);
-
-/* return the global input mapping sequence for the given type/player */
-const input_seq &input_type_seq(running_machine &machine, int type, int player, input_seq_type seqtype);
-/* change the global input sequence for the given type/player */
-void input_type_set_seq(running_machine &machine, int type, int player, input_seq_type seqtype, const input_seq *newseq);
+//**************************************************************************
+// INLINE TEMPLATES
+//**************************************************************************
-/* return TRUE if the sequence for the given input type/player is pressed */
-int input_type_pressed(running_machine &machine, int type, int player);
-
-/* return the list of default mappings */
-const simple_list<input_type_entry> &input_type_list(running_machine &machine);
-
-
-
-/* ----- accessors for input fields ----- */
-
-/* return the expanded string name of the field */
-const char *input_field_name(const input_field_config *field);
-
-/* return the input sequence for the given input field */
-const input_seq &input_field_seq(const input_field_config *field, input_seq_type seqtype);
-
-/* return the current settings for the given input field */
-void input_field_get_user_settings(const input_field_config *field, input_field_user_settings *settings);
-
-/* modify the current settings for the given input field */
-void input_field_set_user_settings(const input_field_config *field, const input_field_user_settings *settings);
-
-/* return the expanded setting name for a field */
-const char *input_field_setting_name(const input_field_config *field);
-
-/* return TRUE if the given field has a "previous" setting */
-int input_field_has_previous_setting(const input_field_config *field);
-
-/* select the previous item for a DIP switch or configuration field */
-void input_field_select_previous_setting(const input_field_config *field);
-
-/* return TRUE if the given field has a "next" setting */
-int input_field_has_next_setting(const input_field_config *field);
-
-/* select the next item for a DIP switch or configuration field */
-void input_field_select_next_setting(const input_field_config *field);
-
-
-/* ----- port checking ----- */
-
-/* return whether an input port exists */
-bool input_port_exists(running_machine &machine, const char *tag);
-
-/* return a bitmask of which bits of an input port are active (i.e. not unused or unknown) */
-input_port_value input_port_active(running_machine &machine, const char *tag);
-
-/* return a bitmask of which bits of an input port are active (i.e. not unused or unknown), or a default value if the port does not exist */
-input_port_value input_port_active_safe(running_machine &machine, const char *tag, input_port_value defvalue);
-
-
-/* ----- port reading ----- */
-
-/* return the value of an input port */
-input_port_value input_port_read_direct(const input_port_config *port);
-
-/* return the value of an input port specified by tag */
-input_port_value input_port_read(running_machine &machine, const char *tag);
-
-/* return the value of a device input port specified by tag */
-input_port_value input_port_read(device_t &device, const char *tag);
-
-/* return the value of an input port specified by tag, or a default value if the port does not exist */
-input_port_value input_port_read_safe(running_machine &machine, const char *tag, input_port_value defvalue);
-
-/* return the extracted crosshair values for the given player */
-int input_port_get_crosshair_position(running_machine &machine, int player, float *x, float *y);
-
-/* force an update to the input port values based on current conditions */
-void input_port_update_defaults(running_machine &machine);
-
-
-
-/* ----- port writing ----- */
-
-/* write a value to a port */
-void input_port_write_direct(const input_port_config *port, input_port_value value, input_port_value mask);
-
-/* write a value to a port specified by tag */
-void input_port_write(running_machine &machine, const char *tag, input_port_value value, input_port_value mask);
-
-/* write a value to a port, ignore if the port does not exist */
-void input_port_write_safe(running_machine &machine, const char *tag, input_port_value value, input_port_value mask);
-
-
-
-/* ----- misc helper functions ----- */
-
-/* return the TRUE if the given condition attached is true */
-int input_condition_true(running_machine &machine, const input_condition *condition,device_t &owner);
-
-/* convert an input_port_token to a default string */
-const char *input_port_string_from_token(const char *token);
-
-/* return TRUE if machine use full keyboard emulation */
-int input_machine_has_keyboard(running_machine &machine);
-
-/* these are called by the core; they should not be called from FEs */
-void inputx_init(running_machine &machine);
-
-/* called by drivers to setup natural keyboard support */
-void inputx_setup_natural_keyboard(running_machine &machine,
- int (*queue_chars)(running_machine &machine, const unicode_char *text, size_t text_len),
- int (*accept_char)(running_machine &machine, unicode_char ch),
- int (*charqueue_empty)(running_machine &machine));
-
-/* validity checks */
-int validate_natural_keyboard_statics(void);
-
-/* these can be called from FEs */
-int inputx_can_post(running_machine &machine);
-
-/* various posting functions; can be called from FEs */
-void inputx_postc(running_machine &machine, unicode_char ch);
-void inputx_post_utf8(running_machine &machine, const char *text);
-void inputx_post_utf8_rate(running_machine &machine, const char *text, attotime rate);
-int inputx_is_posting(running_machine &machine);
+template<int (*_FunctionPointer)(device_t *)>
+ioport_value ioport_read_line_wrapper(device_t &device, ioport_field &field, void *param)
+{
+ return (*_FunctionPointer)(&device);
+}
-/* miscellaneous functions */
-int input_classify_port(const input_field_config *field);
-int input_has_input_class(running_machine &machine, int inputclass);
-int input_player_number(const input_field_config *field);
-int input_count_players(running_machine &machine);
+template<class _FunctionClass, int (_FunctionClass::*_FunctionPointer)()>
+ioport_value ioport_read_line_wrapper(_FunctionClass &device, ioport_field &field, void *param)
+{
+ return (device.*_FunctionPointer)();
+}
+template<void (*_FunctionPointer)(device_t *, int)>
+void ioport_write_line_wrapper(device_t &device, ioport_field &field, void *param, ioport_value oldval, ioport_value newval)
+{
+ return (*_FunctionPointer)(&device, newval);
+}
-inline running_machine &input_field_config::machine() const
+template<class _FunctionClass, void (_FunctionClass::*_FunctionPointer)(int)>
+void ioport_write_line_wrapper(_FunctionClass &device, ioport_field &field, void *param, ioport_value oldval, ioport_value newval)
{
- return m_port.machine();
+ return (device.*_FunctionPointer)(newval);
}
-// temporary construction helpers
-void field_config_insert(input_field_config &newfield, input_port_value &disallowedbits, astring &errorbuf);
-void diplocation_list_alloc(input_field_config &field, const char *location, astring &errorbuf);
+//**************************************************************************
+// INLINE FUNCITONS
+//**************************************************************************
+
+inline ioport_manager &ioport_field::manager() const { return m_port.manager(); }
+inline device_t &ioport_field::device() const { return m_port.device(); }
+inline running_machine &ioport_field::machine() const { return m_port.machine(); }
+
+inline device_t &ioport_setting::device() const { return m_field.device(); }
+inline running_machine &ioport_setting::machine() const { return m_field.machine(); }
-input_port_config *ioconfig_alloc_port(ioport_list &portlist, device_t &device, const char *tag);
-input_port_config *ioconfig_modify_port(ioport_list &portlist, device_t &device, const char *tag);
-input_field_config *ioconfig_alloc_field(input_port_config &port, int type, input_port_value defval, input_port_value mask, const char *name = NULL);
-input_field_config *ioconfig_alloc_onoff(input_port_config &port, const char *name, input_port_value defval, input_port_value mask, const char *diplocation, astring &errorbuf);
-input_setting_config *ioconfig_alloc_setting(input_field_config &field, input_port_value value, const char *name);
-void ioconfig_field_add_char(input_field_config &field, unicode_char ch, astring &errorbuf);
-void ioconfig_add_code(input_field_config &field, int which, input_code code);
-#endif /* __INPTPORT_H__ */
+#endif // __INPTPORT_H__ */
diff --git a/src/emu/machine.c b/src/emu/machine.c
index 55bcbaa565f..86b5aff6a23 100644
--- a/src/emu/machine.c
+++ b/src/emu/machine.c
@@ -284,9 +284,6 @@ void running_machine::start()
// allocate the gfx elements prior to device initialization
gfx_init(*this);
- // initialize natural keyboard support
- inputx_init(*this);
-
// initialize image devices
image_init(*this);
m_tilemap = auto_alloc(*this, tilemap_manager(*this));
diff --git a/src/emu/machine/generic.c b/src/emu/machine/generic.c
index 54e4d93dd38..fdec7134531 100644
--- a/src/emu/machine/generic.c
+++ b/src/emu/machine/generic.c
@@ -528,7 +528,7 @@ void set_led_status(running_machine &machine, int num, int on)
CUSTOM_INPUT_MEMBER( driver_device::custom_port_read )
{
const char *tag = (const char *)param;
- return input_port_read(machine(), tag);
+ return ioport(tag)->read();
}
diff --git a/src/emu/machine/jvsdev.c b/src/emu/machine/jvsdev.c
index ebed2095d40..d80169d0920 100644
--- a/src/emu/machine/jvsdev.c
+++ b/src/emu/machine/jvsdev.c
@@ -249,6 +249,6 @@ void jvs_device::handle_output(const char *tag, UINT8 id, UINT8 val)
case 2: jvs_outputs ^= m; break;
}
- input_port_write_safe(machine(), tag, jvs_outputs, m);
+ machine().root_device().ioport(tag)->write_safe(jvs_outputs, m);
}
diff --git a/src/emu/machine/microtch.c b/src/emu/machine/microtch.c
index 1ca1ae76edc..7315cdbd7fe 100644
--- a/src/emu/machine/microtch.c
+++ b/src/emu/machine/microtch.c
@@ -82,8 +82,8 @@ void microtouch_device::send_format_decimal_packet(int x, int y)
void microtouch_device::send_touch_packet()
{
- int tx = input_port_read(*this, "TOUCH_X");
- int ty = input_port_read(*this, "TOUCH_Y");
+ int tx = ioport("TOUCH_X")->read();
+ int ty = ioport("TOUCH_Y")->read();
if ( m_out_touch_cb == NULL ||
m_out_touch_cb( &tx, &ty ) != 0 )
@@ -127,7 +127,7 @@ void microtouch_device::device_timer(emu_timer &timer, device_timer_id id, int p
}
// send format tablet packet
- if ( input_port_read(*this, "TOUCH") & 0x01 )
+ if ( ioport("TOUCH")->read() & 0x01 )
{
send_touch_packet();
}
diff --git a/src/emu/memory.c b/src/emu/memory.c
index 1ca92ac8a9d..fc9f48ea49c 100644
--- a/src/emu/memory.c
+++ b/src/emu/memory.c
@@ -397,7 +397,7 @@ public:
void set_legacy_func(device_t &device, read64_device_func func, const char *name, UINT64 mask = 0);
// configure I/O port access
- void set_ioport(const input_port_config &ioport);
+ void set_ioport(ioport_port &ioport);
// read via the underlying delegates
UINT8 read8(address_space &space, offs_t offset, UINT8 mask) const { return m_read.r8(space, offset, mask); }
@@ -419,7 +419,7 @@ private:
// stubs for reading I/O ports
template<typename _UintType>
- _UintType read_stub_ioport(address_space &space, offs_t offset, _UintType mask) { return input_port_read_direct(m_ioport); }
+ _UintType read_stub_ioport(address_space &space, offs_t offset, _UintType mask) { return m_ioport->read(); }
// internal helper
virtual void remove_subunit(int entry);
@@ -427,7 +427,7 @@ private:
// internal state
access_handler m_read;
access_handler m_subread[8];
- const input_port_config * m_ioport;
+ ioport_port * m_ioport;
bool m_sub_is_legacy[8];
legacy_info m_legacy_info;
@@ -504,7 +504,7 @@ public:
void set_legacy_func(device_t &device, write64_device_func func, const char *name, UINT64 mask = 0);
// configure I/O port access
- void set_ioport(const input_port_config &ioport);
+ void set_ioport(ioport_port &ioport);
// write via the underlying delegates
void write8(address_space &space, offs_t offset, UINT8 data, UINT8 mask) const { m_write.w8(space, offset, data, mask); }
@@ -526,7 +526,7 @@ private:
// stubs for writing I/O ports
template<typename _UintType>
- void write_stub_ioport(address_space &space, offs_t offset, _UintType data, _UintType mask) { input_port_write_direct(m_ioport, data, mask); }
+ void write_stub_ioport(address_space &space, offs_t offset, _UintType data, _UintType mask) { m_ioport->write(data, mask); }
// internal helper
virtual void remove_subunit(int entry);
@@ -534,7 +534,7 @@ private:
// internal state
access_handler m_write;
access_handler m_subwrite[8];
- const input_port_config * m_ioport;
+ ioport_port * m_ioport;
bool m_sub_is_legacy[8];
legacy_info m_legacy_info;
@@ -571,7 +571,7 @@ public:
}
// forward I/O port access configuration
- void set_ioport(const input_port_config &ioport) const {
+ void set_ioport(ioport_port &ioport) const {
for (typename std::list<_HandlerEntry *>::const_iterator i = handlers.begin(); i != handlers.end(); i++)
(*i)->set_ioport(ioport);
}
@@ -2323,7 +2323,7 @@ void address_space::install_readwrite_port(offs_t addrstart, offs_t addrend, off
{
// find the port
astring fulltag;
- input_port_config *port = machine().root_device().ioport(device().siblingtag(fulltag, rtag));
+ ioport_port *port = machine().root_device().ioport(device().siblingtag(fulltag, rtag));
if (port == NULL)
throw emu_fatalerror("Attempted to map non-existent port '%s' for read in space %s of device '%s'\n", rtag, m_name, m_device.tag());
@@ -2335,7 +2335,7 @@ void address_space::install_readwrite_port(offs_t addrstart, offs_t addrend, off
{
// find the port
astring fulltag;
- input_port_config *port = machine().root_device().ioport(device().siblingtag(fulltag, wtag));
+ ioport_port *port = machine().root_device().ioport(device().siblingtag(fulltag, wtag));
if (port == NULL)
fatalerror("Attempted to map non-existent port '%s' for write in space %s of device '%s'\n", wtag, m_name, m_device.tag());
@@ -4958,7 +4958,7 @@ void handler_entry_read::set_legacy_func(device_t &device, read64_device_func fu
// of the appropriate size
//-------------------------------------------------
-void handler_entry_read::set_ioport(const input_port_config &ioport)
+void handler_entry_read::set_ioport(ioport_port &ioport)
{
m_ioport = &ioport;
if (m_datawidth == 8)
@@ -5413,7 +5413,7 @@ void handler_entry_write::set_legacy_func(device_t &device, write64_device_func
// of the appropriate size
//-------------------------------------------------
-void handler_entry_write::set_ioport(const input_port_config &ioport)
+void handler_entry_write::set_ioport(ioport_port &ioport)
{
m_ioport = &ioport;
if (m_datawidth == 8)
diff --git a/src/emu/rendlay.c b/src/emu/rendlay.c
index 51a9c09ec9a..2c502cf031d 100644
--- a/src/emu/rendlay.c
+++ b/src/emu/rendlay.c
@@ -2208,9 +2208,13 @@ int layout_view::item::state() const
// if configured to an input, fetch the input value
else if (m_input_tag[0] != 0)
{
- const input_field_config *field = input_field_by_tag_and_mask(m_element->machine(), m_input_tag, m_input_mask);
- if (field != NULL)
- state = ((input_port_read_safe(m_element->machine(), m_input_tag, 0) ^ field->defvalue) & m_input_mask) ? 1 : 0;
+ ioport_port *port = m_element->machine().root_device().ioport(m_input_tag);
+ if (port != NULL)
+ {
+ ioport_field *field = port->field(m_input_mask);
+ if (field != NULL)
+ state = ((port->read() ^ field->defvalue()) & m_input_mask) ? 1 : 0;
+ }
}
return state;
}
diff --git a/src/emu/screen.c b/src/emu/screen.c
index aece8df6d93..05aa8ac141b 100644
--- a/src/emu/screen.c
+++ b/src/emu/screen.c
@@ -782,6 +782,17 @@ void screen_device::register_screen_bitmap(bitmap_t &bitmap)
//-------------------------------------------------
+// vblank_port_read - custom port handler to
+// return a VBLANK state
+//-------------------------------------------------
+
+int screen_device::vblank_port_read()
+{
+ return vblank();
+}
+
+
+//-------------------------------------------------
// vblank_begin - call any external callbacks to
// signal the VBLANK period has begun
//-------------------------------------------------
diff --git a/src/emu/screen.h b/src/emu/screen.h
index ed141513c18..c89f227c1b7 100644
--- a/src/emu/screen.h
+++ b/src/emu/screen.h
@@ -227,6 +227,7 @@ public:
// additional helpers
void register_vblank_callback(vblank_state_delegate vblank_callback);
void register_screen_bitmap(bitmap_t &bitmap);
+ int vblank_port_read();
// internal to the video system
bool update_quads();
diff --git a/src/emu/sound/disc_cls.h b/src/emu/sound/disc_cls.h
index e6be420716f..bbdad7b3391 100644
--- a/src/emu/sound/disc_cls.h
+++ b/src/emu/sound/disc_cls.h
@@ -149,7 +149,7 @@ public:
void step(void);
void reset(void);
private:
- const input_port_config *m_port;
+ ioport_port *m_port;
INT32 m_lastpval;
INT32 m_pmin;
double m_pscale;
diff --git a/src/emu/sound/disc_inp.c b/src/emu/sound/disc_inp.c
index d34505afe63..02fe15fa186 100644
--- a/src/emu/sound/disc_inp.c
+++ b/src/emu/sound/disc_inp.c
@@ -55,7 +55,7 @@ WRITE8_DEVICE_HANDLER(discrete_sound_w)
DISCRETE_STEP(dss_adjustment)
{
- INT32 rawportval = input_port_read_direct(m_port);
+ INT32 rawportval = m_port->read();
/* only recompute if the value changed from last time */
if (UNEXPECTED(rawportval != m_lastpval))
diff --git a/src/emu/ui.c b/src/emu/ui.c
index 820928da2da..648c6b4236d 100644
--- a/src/emu/ui.c
+++ b/src/emu/ui.c
@@ -935,7 +935,7 @@ static astring &warnings_string(running_machine &machine, astring &string)
string.cat(" have not been correctly dumped.\n");
}
/* add one line per warning flag */
- if (input_machine_has_keyboard(machine))
+ if (machine.ioport().has_keyboard())
string.cat("The keyboard emulation may not be 100% accurate.\n");
if (machine.system().flags & GAME_IMPERFECT_COLORS)
string.cat("The colors aren't 100% accurate.\n");
@@ -1213,7 +1213,7 @@ static void process_natural_keyboard(running_machine &machine)
{
/* if this was a UI_EVENT_CHAR event, post it */
if (event.event_type == UI_EVENT_CHAR)
- inputx_postc(machine, event.ch);
+ machine.ioport().natkeyboard().post(event.ch);
}
/* process natural keyboard keys that don't get UI_EVENT_CHARs */
@@ -1236,7 +1236,7 @@ static void process_natural_keyboard(running_machine &machine)
*key_down_ptr |= key_down_mask;
/* post the key */
- inputx_postc(machine, UCHAR_MAMEKEY_BEGIN + code.item_id());
+ machine.ioport().natkeyboard().post(UCHAR_MAMEKEY_BEGIN + code.item_id());
}
else if (!pressed && (*key_down_ptr & key_down_mask))
{
@@ -1259,7 +1259,7 @@ void ui_paste(running_machine &machine)
if (text != NULL)
{
/* post the text */
- inputx_post_utf8(machine, text);
+ machine.ioport().natkeyboard().post_utf8(text);
/* free the string */
osd_free(text);
@@ -1317,10 +1317,10 @@ static UINT32 handler_ingame(running_machine &machine, render_container *contain
}
/* determine if we should disable the rest of the UI */
- int ui_disabled = (input_machine_has_keyboard(machine) && !machine.ui_active());
+ int ui_disabled = (machine.ioport().has_keyboard() && !machine.ui_active());
/* is ScrLk UI toggling applicable here? */
- if (input_machine_has_keyboard(machine))
+ if (machine.ioport().has_keyboard())
{
/* are we toggling the UI with ScrLk? */
if (ui_input_pressed(machine, IPT_UI_TOGGLE_UI))
@@ -1488,7 +1488,7 @@ static UINT32 handler_ingame(running_machine &machine, render_container *contain
machine.video().set_throttled(!machine.video().throttled());
/* check for fast forward */
- if (input_type_pressed(machine, IPT_UI_FAST_FORWARD, 0))
+ if (machine.ioport().type_pressed(IPT_UI_FAST_FORWARD))
{
machine.video().set_fastforward(true);
ui_show_fps_temp(0.5);
@@ -1640,8 +1640,8 @@ static slider_state *slider_alloc(running_machine &machine, const char *title, I
static slider_state *slider_init(running_machine &machine)
{
- input_field_config *field;
- input_port_config *port;
+ ioport_field *field;
+ ioport_port *port;
slider_state *listhead = NULL;
slider_state **tailptr = &listhead;
astring string;
@@ -1666,11 +1666,11 @@ static slider_state *slider_init(running_machine &machine)
/* add analog adjusters */
for (port = machine.ioport().first_port(); port != NULL; port = port->next())
- for (field = port->fieldlist().first(); field != NULL; field = field->next())
- if (field->type == IPT_ADJUSTER)
+ for (field = port->first_field(); field != NULL; field = field->next())
+ if (field->type() == IPT_ADJUSTER)
{
void *param = (void *)field;
- *tailptr = slider_alloc(machine, field->name, 0, field->defvalue, 100, 1, slider_adjuster, param);
+ *tailptr = slider_alloc(machine, field->name(), 0, field->defvalue(), 100, 1, slider_adjuster, param);
tailptr = &(*tailptr)->next;
}
@@ -1772,14 +1772,14 @@ static slider_state *slider_init(running_machine &machine)
#ifdef MAME_DEBUG
/* add crosshair adjusters */
for (port = machine.ioport().first_port(); port != NULL; port = port->next())
- for (field = port->fieldlist().first(); field != NULL; field = field->next())
- if (field->crossaxis != CROSSHAIR_AXIS_NONE && field->player == 0)
+ for (field = port->first_field(); field != NULL; field = field->next())
+ if (field->crosshair_axis() != CROSSHAIR_AXIS_NONE && field->player() == 0)
{
void *param = (void *)field;
- string.printf("Crosshair Scale %s", (field->crossaxis == CROSSHAIR_AXIS_X) ? "X" : "Y");
+ string.printf("Crosshair Scale %s", (field->crosshair_axis() == CROSSHAIR_AXIS_X) ? "X" : "Y");
*tailptr = slider_alloc(machine, string, -3000, 1000, 3000, 100, slider_crossscale, param);
tailptr = &(*tailptr)->next;
- string.printf("Crosshair Offset %s", (field->crossaxis == CROSSHAIR_AXIS_X) ? "X" : "Y");
+ string.printf("Crosshair Offset %s", (field->crosshair_axis() == CROSSHAIR_AXIS_X) ? "X" : "Y");
*tailptr = slider_alloc(machine, string, -3000, 0, 3000, 100, slider_crossoffset, param);
tailptr = &(*tailptr)->next;
}
@@ -1832,14 +1832,14 @@ static INT32 slider_mixervol(running_machine &machine, void *arg, astring *strin
static INT32 slider_adjuster(running_machine &machine, void *arg, astring *string, INT32 newval)
{
- const input_field_config *field = (const input_field_config *)arg;
- input_field_user_settings settings;
+ ioport_field *field = (ioport_field *)arg;
+ ioport_field::user_settings settings;
- input_field_get_user_settings(field, &settings);
+ field->get_user_settings(settings);
if (newval != SLIDER_NOCHANGE)
{
settings.value = newval;
- input_field_set_user_settings(field, &settings);
+ field->set_user_settings(settings);
}
if (string != NULL)
string->printf("%d%%", settings.value);
@@ -2185,13 +2185,13 @@ static char *slider_get_screen_desc(screen_device &screen)
#ifdef MAME_DEBUG
static INT32 slider_crossscale(running_machine &machine, void *arg, astring *string, INT32 newval)
{
- input_field_config *field = (input_field_config *)arg;
+ ioport_field *field = (ioport_field *)arg;
if (newval != SLIDER_NOCHANGE)
- field->crossscale = (float)newval * 0.001f;
+ field->set_crosshair_scale(float(newval) * 0.001);
if (string != NULL)
- string->printf("%s %s %1.3f", "Crosshair Scale", (field->crossaxis == CROSSHAIR_AXIS_X) ? "X" : "Y", (float)newval * 0.001f);
- return floor(field->crossscale * 1000.0f + 0.5f);
+ string->printf("%s %s %1.3f", "Crosshair Scale", (field->crosshair_axis() == CROSSHAIR_AXIS_X) ? "X" : "Y", float(newval) * 0.001f);
+ return floor(field->crosshair_scale() * 1000.0f + 0.5f);
}
#endif
@@ -2204,13 +2204,13 @@ static INT32 slider_crossscale(running_machine &machine, void *arg, astring *str
#ifdef MAME_DEBUG
static INT32 slider_crossoffset(running_machine &machine, void *arg, astring *string, INT32 newval)
{
- input_field_config *field = (input_field_config *)arg;
+ ioport_field *field = (ioport_field *)arg;
if (newval != SLIDER_NOCHANGE)
- field->crossoffset = (float)newval * 0.001f;
+ field->set_crosshair_offset(float(newval) * 0.001f);
if (string != NULL)
- string->printf("%s %s %1.3f", "Crosshair Offset", (field->crossaxis == CROSSHAIR_AXIS_X) ? "X" : "Y", (float)newval * 0.001f);
- return field->crossoffset;
+ string->printf("%s %s %1.3f", "Crosshair Offset", (field->crosshair_axis() == CROSSHAIR_AXIS_X) ? "X" : "Y", float(newval) * 0.001f);
+ return field->crosshair_offset();
}
#endif
diff --git a/src/emu/uiinput.c b/src/emu/uiinput.c
index 2cb781a5d19..1be9eeb3c52 100644
--- a/src/emu/uiinput.c
+++ b/src/emu/uiinput.c
@@ -37,8 +37,8 @@ enum
struct _ui_input_private
{
/* pressed states; retrieved with ui_input_pressed() */
- osd_ticks_t next_repeat[__ipt_max];
- UINT8 seqpressed[__ipt_max];
+ osd_ticks_t next_repeat[IPT_COUNT];
+ UINT8 seqpressed[IPT_COUNT];
/* mouse position/info */
render_target * current_mouse_target;
@@ -97,12 +97,11 @@ void ui_input_init(running_machine &machine)
void ui_input_frame_update(running_machine &machine)
{
ui_input_private *uidata = machine.ui_input_data;
- int code;
/* update the state of all the UI keys */
- for (code = __ipt_ui_start; code <= __ipt_ui_end; code++)
+ for (ioport_type code = ioport_type(IPT_UI_FIRST + 1); code < IPT_UI_LAST; code++)
{
- int pressed = machine.input().seq_pressed(input_type_seq(machine, code, 0, SEQ_TYPE_STANDARD));
+ bool pressed = machine.ioport().type_pressed(code);
if (!pressed || uidata->seqpressed[code] != SEQ_PRESSED_RESET)
uidata->seqpressed[code] = pressed;
}
@@ -199,7 +198,7 @@ void ui_input_reset(running_machine &machine)
uidata->events_start = 0;
uidata->events_end = 0;
- for (code = __ipt_ui_start; code <= __ipt_ui_end; code++)
+ for (code = IPT_UI_FIRST + 1; code < IPT_UI_LAST; code++)
{
uidata->seqpressed[code] = SEQ_PRESSED_RESET;
uidata->next_repeat[code] = 0;
diff --git a/src/emu/uimain.c b/src/emu/uimain.c
index 85af3575eeb..48538e7a573 100644
--- a/src/emu/uimain.c
+++ b/src/emu/uimain.c
@@ -109,8 +109,8 @@ ui_menu_main::ui_menu_main(running_machine &machine, render_container *container
void ui_menu_main::populate()
{
- input_field_config *field;
- input_port_config *port;
+ ioport_field *field;
+ ioport_port *port;
int has_configs = false;
int has_analog = false;
int has_dips = false;
@@ -118,13 +118,13 @@ void ui_menu_main::populate()
astring menu_text;
/* scan the input port array to see what options we need to enable */
for (port = machine().ioport().first_port(); port != NULL; port = port->next())
- for (field = port->fieldlist().first(); field != NULL; field = field->next())
+ for (field = port->first_field(); field != NULL; field = field->next())
{
- if (field->type == IPT_DIPSWITCH)
+ if (field->type() == IPT_DIPSWITCH)
has_dips = true;
- if (field->type == IPT_CONFIG)
+ if (field->type() == IPT_CONFIG)
has_configs = true;
- if (input_type_is_analog(field->type))
+ if (field->is_analog())
has_analog = true;
}
device_iterator deviter(machine().root_device());
@@ -192,7 +192,7 @@ void ui_menu_main::populate()
}
/* add keyboard mode menu */
- if (input_machine_has_keyboard(machine()) && inputx_can_post(machine()))
+ if (machine().ioport().has_keyboard() && machine().ioport().natkeyboard().can_post())
item_append("Keyboard Mode", NULL, 0, (void *)KEYBOARD_MODE);
/* add sliders menu */
@@ -671,10 +671,10 @@ void ui_menu_input_general::populate()
suborder[SEQ_TYPE_INCREMENT] = 2;
/* iterate over the input ports and add menu items */
- for (input_type_entry *entry = input_type_list(machine()).first(); entry != NULL; entry = entry->next())
+ for (input_type_entry *entry = machine().ioport().first_type(); entry != NULL; entry = entry->next())
/* add if we match the group and we have a valid name */
- if (entry->group == group && entry->name != NULL && entry->name[0] != 0)
+ if (entry->group() == group && entry->name() != NULL && entry->name()[0] != 0)
{
input_seq_type seqtype;
@@ -689,11 +689,11 @@ void ui_menu_input_general::populate()
if(pollingitem && pollingref == entry && pollingseq == seqtype)
pollingitem = item;
item->seqtype = seqtype;
- item->seq = input_type_seq(machine(), entry->type, entry->player, seqtype);
- item->defseq = &entry->defseq[seqtype];
+ item->seq = machine().ioport().type_seq(entry->type(), entry->player(), seqtype);
+ item->defseq = &entry->defseq(seqtype);
item->sortorder = sortorder * 4 + suborder[seqtype];
- item->type = input_type_is_analog(entry->type) ? (INPUT_TYPE_ANALOG + seqtype) : INPUT_TYPE_DIGITAL;
- item->name = entry->name;
+ item->type = ioport_manager::type_is_analog(entry->type()) ? (INPUT_TYPE_ANALOG + seqtype) : INPUT_TYPE_DIGITAL;
+ item->name = entry->name();
item->next = itemlist;
itemlist = item;
@@ -723,8 +723,8 @@ ui_menu_input_specific::ui_menu_input_specific(running_machine &machine, render_
void ui_menu_input_specific::populate()
{
input_item_data *itemlist = NULL;
- input_field_config *field;
- input_port_config *port;
+ ioport_field *field;
+ ioport_port *port;
int suborder[SEQ_TYPE_TOTAL];
astring tempstring;
@@ -735,22 +735,22 @@ void ui_menu_input_specific::populate()
/* iterate over the input ports and add menu items */
for (port = machine().ioport().first_port(); port != NULL; port = port->next())
- for (field = port->fieldlist().first(); field != NULL; field = field->next())
+ for (field = port->first_field(); field != NULL; field = field->next())